{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 100 Numpy Exercises\n",
    "\n",
    "[numpy-100](https://github.com/rougier/numpy-100)中文版及一些注解。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1. 导入Numpy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:32.699969Z",
     "start_time": "2019-09-11T03:49:32.617125Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. 打印Numpy版本号及其配置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:32.772473Z",
     "start_time": "2019-09-11T03:49:32.703245Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.16.2'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:32.950061Z",
     "start_time": "2019-09-11T03:49:32.776738Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mkl_info:\n",
      "    libraries = ['mkl_rt', 'pthread']\n",
      "    library_dirs = ['/home/shensir/anaconda3/lib']\n",
      "    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]\n",
      "    include_dirs = ['/home/shensir/anaconda3/include']\n",
      "blas_mkl_info:\n",
      "    libraries = ['mkl_rt', 'pthread']\n",
      "    library_dirs = ['/home/shensir/anaconda3/lib']\n",
      "    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]\n",
      "    include_dirs = ['/home/shensir/anaconda3/include']\n",
      "blas_opt_info:\n",
      "    libraries = ['mkl_rt', 'pthread']\n",
      "    library_dirs = ['/home/shensir/anaconda3/lib']\n",
      "    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]\n",
      "    include_dirs = ['/home/shensir/anaconda3/include']\n",
      "lapack_mkl_info:\n",
      "    libraries = ['mkl_rt', 'pthread']\n",
      "    library_dirs = ['/home/shensir/anaconda3/lib']\n",
      "    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]\n",
      "    include_dirs = ['/home/shensir/anaconda3/include']\n",
      "lapack_opt_info:\n",
      "    libraries = ['mkl_rt', 'pthread']\n",
      "    library_dirs = ['/home/shensir/anaconda3/lib']\n",
      "    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]\n",
      "    include_dirs = ['/home/shensir/anaconda3/include']\n"
     ]
    }
   ],
   "source": [
    "np.show_config()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3. 创建一个长度(size)为10的向量(vector)\n",
    "\n",
    "注意这里就是创建一个`np.ndarray`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:33.066448Z",
     "start_time": "2019-09-11T03:49:32.952997Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros(10)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4. 计算数组的内存大小"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:33.178978Z",
     "start_time": "2019-09-11T03:49:33.071288Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "800 bytes\n"
     ]
    }
   ],
   "source": [
    "z = np.zeros((10, 10))\n",
    "print(\"%d bytes\" % (z.size * z.itemsize))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意这里就是简单的把总元素个数`z.size`（100）， 乘上单个元素所占的内存`z.itemsize`(8 bytes)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 5. 在命令行打印出Numpy中add函数的帮助文档信息"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里主要是有关命令行调用Python的问题，我们可以在命令行从`python --help`开始， 找到`python -c`符合我们的要求，所以这里只需要在命令行执行`python -c \"import numpy; numpy.info(numpy.add)\"`即可。就等同于在Python解释器中执行如下程序：\n",
    "```python\n",
    "import numpy\n",
    "numpy.info(numpy.add)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "此外，针对Numpy,我们可以有很多种方式查看文档:上面的`np.info(np.add)`, 以及利用help的`help(np.add)`, 和比较少用的doc方法的调用`print(np.add.__doc__)`（输出和`np.info`一致）, 一般来说用`np.info`就可以了，也比较方便。如果使用`IPython`的话，可以直接`np.add?`回车"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 6. 创建一个长度为10的向量，其第五个值为1， 其他为0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:33.298830Z",
     "start_time": "2019-09-11T03:49:33.183197Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 1., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros(10)\n",
    "z[4] = 1\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 7. 创建一个包含从10到49所有整数的向量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:33.431088Z",
     "start_time": "2019-09-11T03:49:33.302201Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,\n",
       "       27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,\n",
       "       44, 45, 46, 47, 48, 49])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(10, 50)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意Python也有内建函数`range`具有相似的功能，相对而言，Numpy的`arange`由于使用了内存优化技术，其效率要高很多。我们可以做个简单的水平对比。例子来自*Scipy Lecture Notes*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:36.102891Z",
     "start_time": "2019-09-11T03:49:33.434005Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "317 µs ± 7.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit [i**2 for i in range(1000)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:40.255287Z",
     "start_time": "2019-09-11T03:49:36.106755Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.13 µs ± 842 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit a = np.arange(1000) ** 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 8. 反转一个向量（逆序）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:40.269259Z",
     "start_time": "2019-09-11T03:49:40.259880Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:40.475272Z",
     "start_time": "2019-09-11T03:49:40.272776Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = z[::-1]\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 9. 创建一个3x3的矩阵， 包含数字0到8"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:40.619246Z",
     "start_time": "2019-09-11T03:49:40.477495Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [3, 4, 5],\n",
       "       [6, 7, 8]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(0, 9).reshape(3, 3)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里可以在原题目的基础上进行拓展，上面的实现中0到8是可以看作以行为顺序，如我我们希望0到8以列为顺序排列呢？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:40.765815Z",
     "start_time": "2019-09-11T03:49:40.624184Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 3, 6],\n",
       "       [1, 4, 7],\n",
       "       [2, 5, 8]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 列为顺序\n",
    "z = np.arange(0, 9).reshape(3, 3).T\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其实只需要把原来的矩阵转置就可以了:-)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 10. 找出[1,2,0,0,4,0] 中非0数字的位置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:40.917616Z",
     "start_time": "2019-09-11T03:49:40.768428Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 1, 4]),)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.array([1,2,0,0,4,0])\n",
    "z.nonzero()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 11. 创建3x3的单位矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:41.120723Z",
     "start_time": "2019-09-11T03:49:40.922828Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0.],\n",
       "       [0., 1., 0.],\n",
       "       [0., 0., 1.]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.eye(3)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 12. 创建3x3x3数组，以随机数字填充"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:41.232475Z",
     "start_time": "2019-09-11T03:49:41.126731Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0.22223755, 0.02993117, 0.4890893 ],\n",
       "        [0.0820244 , 0.67123686, 0.30827137],\n",
       "        [0.7508472 , 0.81738707, 0.84870083]],\n",
       "\n",
       "       [[0.65084705, 0.40438861, 0.04736435],\n",
       "        [0.09258906, 0.50895712, 0.34483339],\n",
       "        [0.91449234, 0.16814904, 0.86294636]],\n",
       "\n",
       "       [[0.56517313, 0.13952306, 0.76674818],\n",
       "        [0.04259055, 0.28120883, 0.13086924],\n",
       "        [0.11580096, 0.91740276, 0.24734521]]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random((3, 3, 3))\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 13. 创建10x10数组，以随机数字填充，并找出其中的最大值和最小值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:41.398412Z",
     "start_time": "2019-09-11T03:49:41.235214Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.12752282, 0.79054209, 0.50129149, 0.58857169, 0.35450135,\n",
       "        0.39841021, 0.17807883, 0.88929081, 0.97780616, 0.773384  ],\n",
       "       [0.90780362, 0.64876217, 0.0585608 , 0.26701752, 0.76980913,\n",
       "        0.28396342, 0.86735689, 0.0125925 , 0.40396858, 0.14115772],\n",
       "       [0.8098699 , 0.61503945, 0.30412717, 0.09408111, 0.45769837,\n",
       "        0.47180697, 0.92817308, 0.68631218, 0.17004323, 0.48279816],\n",
       "       [0.58715196, 0.2383897 , 0.28221602, 0.08891016, 0.16125275,\n",
       "        0.00269889, 0.20931989, 0.18024097, 0.11391687, 0.73651609],\n",
       "       [0.25771839, 0.85886099, 0.13783206, 0.92036633, 0.47577829,\n",
       "        0.9711062 , 0.32103083, 0.70490514, 0.52713121, 0.19038581],\n",
       "       [0.30706035, 0.67517319, 0.32025366, 0.08029852, 0.72571681,\n",
       "        0.07372837, 0.86243916, 0.25484642, 0.70585143, 0.08274462],\n",
       "       [0.74795535, 0.8067741 , 0.89113355, 0.47931097, 0.10301097,\n",
       "        0.4847746 , 0.92899191, 0.12575855, 0.88174842, 0.47706755],\n",
       "       [0.92802187, 0.66522839, 0.2899387 , 0.46113872, 0.28817592,\n",
       "        0.20630832, 0.39909759, 0.23957712, 0.98647748, 0.14215   ],\n",
       "       [0.05693348, 0.35706197, 0.0287801 , 0.2528074 , 0.13481535,\n",
       "        0.2227437 , 0.68933693, 0.19408625, 0.20216115, 0.99834648],\n",
       "       [0.0363542 , 0.26831658, 0.50569523, 0.19128829, 0.53549785,\n",
       "        0.49938433, 0.9457238 , 0.31700083, 0.19944951, 0.03825154]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random((10, 10))\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:41.563402Z",
     "start_time": "2019-09-11T03:49:41.402197Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.9983464750382925, 0.0026988893597477137)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.max(), z.min()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 14. 创建长度为10的随机向量，并计算其均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:41.682163Z",
     "start_time": "2019-09-11T03:49:41.568588Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.32286031, 0.59936123, 0.6659822 , 0.00112788, 0.71261922,\n",
       "       0.07623688, 0.23427983, 0.70193797, 0.31707463, 0.6425674 ])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random((10))\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:41.803527Z",
     "start_time": "2019-09-11T03:49:41.684596Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.4274047541501854"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 15. 创建一个二维数组，其边界值为1，内部值为0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.138106Z",
     "start_time": "2019-09-11T03:49:41.805744Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1., 1., 1.],\n",
       "       [1., 0., 0., 0., 1.],\n",
       "       [1., 0., 0., 0., 1.],\n",
       "       [1., 0., 0., 0., 1.],\n",
       "       [1., 1., 1., 1., 1.]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.ones((5, 5))\n",
    "z[1:-1, 1:-1] = 0\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 16. 将现有的数组（nxn）用0组成的边界包裹"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.257544Z",
     "start_time": "2019-09-11T03:49:42.140432Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1.]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.ones((5, 5))\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.402909Z",
     "start_time": "2019-09-11T03:49:42.266277Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0., 0., 0.],\n",
       "       [0., 1., 1., 1., 1., 1., 0.],\n",
       "       [0., 1., 1., 1., 1., 1., 0.],\n",
       "       [0., 1., 1., 1., 1., 1., 0.],\n",
       "       [0., 1., 1., 1., 1., 1., 0.],\n",
       "       [0., 1., 1., 1., 1., 1., 0.],\n",
       "       [0., 0., 0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = np.pad(z, (1, 1), mode='constant', constant_values=0)\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 17. 下列表达式的结果是什么\n",
    "```python\n",
    "0 * np.nan\n",
    "np.nan == np.nan\n",
    "np.inf > np.nan\n",
    "np.nan - np.nan\n",
    "np.nan in set([np.nan])\n",
    "0.3 == 3 * 0.1\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.540817Z",
     "start_time": "2019-09-11T03:49:42.409467Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "nan"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0 * np.nan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-07-26T07:29:13.960984Z",
     "start_time": "2019-07-26T07:29:13.946213Z"
    }
   },
   "source": [
    "有`np.nan`参与的算术操作返回均为`np.nan`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.654735Z",
     "start_time": "2019-09-11T03:49:42.543095Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.nan == np.nan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-07-26T07:31:25.840312Z",
     "start_time": "2019-07-26T07:31:25.834403Z"
    }
   },
   "source": [
    "这里是合理的，比如我们从数据集读出两列数据全部是`np.nan`， 如果上面的表达式设计为返回`True`， \n",
    "那么我们在完全不知道两列数据的情况下就判定二者是相等的，这显然是不合理的。所以这里返回的是`False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.790795Z",
     "start_time": "2019-09-11T03:49:42.657525Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.inf > np.nan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "同样地，我们不能比较无穷大与缺失值的大小"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:42.953977Z",
     "start_time": "2019-09-11T03:49:42.793102Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.nan in set([np.nan])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.098558Z",
     "start_time": "2019-09-11T03:49:42.956231Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0.3 == 3 * 0.1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于浮点数（`float`）运算存在误差，我们不能直接比较其大小。Numpy为我们提供了`np.allclose`函数来比较浮点数之间的近似相等。此外，此函数还支持`np.ndarray`的比较。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.243316Z",
     "start_time": "2019-09-11T03:49:43.101995Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(0.3, 3 * 0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 18. 创建一个5x5的矩阵，其中1，2，3，4正好在矩阵对角线元素下方"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.352756Z",
     "start_time": "2019-09-11T03:49:43.246057Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0, 0, 0],\n",
       "       [1, 0, 0, 0, 0],\n",
       "       [0, 2, 0, 0, 0],\n",
       "       [0, 0, 3, 0, 0],\n",
       "       [0, 0, 0, 4, 0]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.diag(np.arange(1, 5), k=-1)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 19. 创建一个8x8的矩阵，并用0，1标记为国际象棋棋盘的形式\n",
    "如下所示, 黑色部分标记为1.\n",
    "<img src=\"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1564734957&di=10e4e0640ee6888baf9593b9cc877934&imgtype=jpg&er=1&src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F02%2F10%2F13%2F599f0c01a035b_610.jpg\" alt=\"drawing\" width=\"200\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.482723Z",
     "start_time": "2019-09-11T03:49:43.355668Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 1., 0., 1., 0., 1., 0., 1.],\n",
       "       [1., 0., 1., 0., 1., 0., 1., 0.],\n",
       "       [0., 1., 0., 1., 0., 1., 0., 1.],\n",
       "       [1., 0., 1., 0., 1., 0., 1., 0.],\n",
       "       [0., 1., 0., 1., 0., 1., 0., 1.],\n",
       "       [1., 0., 1., 0., 1., 0., 1., 0.],\n",
       "       [0., 1., 0., 1., 0., 1., 0., 1.],\n",
       "       [1., 0., 1., 0., 1., 0., 1., 0.]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros((8, 8))\n",
    "z[1::2, ::2] = 1  # 第2, 4, 6, 8行填充\n",
    "z[::2, 1::2] = 1  # 第1， 3， 5， 7行填充\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 20. 现有维度为6x7x8的数组，找出其中第100个元素的索引(x, y, z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.615740Z",
     "start_time": "2019-09-11T03:49:43.484877Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 5, 3)\n"
     ]
    }
   ],
   "source": [
    "print(np.unravel_index(99, (6, 7, 8)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上面的是给出的答案，一开始我并不知道这个函数，采用了下面的方法，可以作为参考。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.726704Z",
     "start_time": "2019-09-11T03:49:43.620487Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1]), array([5]), array([3]))"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(6*7*8).reshape(6, 7, 8)\n",
    "np.where(z == 99)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是通过Numpy找出来具体位置，但是具体计算的方法并未给出，这里简单解释下。\n",
    "\n",
    "首先，我们可以形象第考虑“数组的维度越往后，对应数据的颗粒度越小”，也就是说，在上面的例子中，我们可以认为6x7x8的立方体是通过如下的方法来构建的：先将所有的一列值(6 * 7 * 8)排成一行，之后每8个组成一个“长条”， 这样就有6*7个长条；之后将每7个长条，上下拼接，铺成一个平面；这样我们就有6个平面，将这6个平面堆起来，就得到了我们最终的“立方体”。\n",
    "\n",
    "那么第100个元素又在哪里呢？为方便起见，我们从“颗粒度”大的开始，依次定位其位置。首先，可以知道每一层含有7*8=56个元素，所以由`100 // 56 = 1`得其位于第二层， 对应到该维度得到索引就是1，即返回的`array[1]`。之后在第二层中继续定位， 去除第一层的56个元素，这里还剩下44个。又由于平面为7x8的，所以由`44 // 8 = 5`得其位于第6行，对应该维度的索引是5， 即返回的`array[5]`, 最后剩下4个元素在新的一行，对应维度的索引为3， 即返回的`array[3]`.由此得到最终的索引为（1， 5， 3）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 21. 用`tile`函数创建一个8x8的棋盘"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:43.839006Z",
     "start_time": "2019-09-11T03:49:43.729988Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 0, 1, 0, 1, 0, 1],\n",
       "       [1, 0, 1, 0, 1, 0, 1, 0],\n",
       "       [0, 1, 0, 1, 0, 1, 0, 1],\n",
       "       [1, 0, 1, 0, 1, 0, 1, 0],\n",
       "       [0, 1, 0, 1, 0, 1, 0, 1],\n",
       "       [1, 0, 1, 0, 1, 0, 1, 0],\n",
       "       [0, 1, 0, 1, 0, 1, 0, 1],\n",
       "       [1, 0, 1, 0, 1, 0, 1, 0]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "unit = np.array([[0, 1], [1, 0]])\n",
    "z = np.tile(unit, (4, 4))\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`tile`的原意就是铺瓷砖，是其作用的一个形象的比喻，这里我们把8x8的棋盘划分为4x4=16块“瓷砖”（这里的`unit`）， 之后将其平铺在一起即可。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 22. 标准化一个5x5的随机矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:44.004250Z",
     "start_time": "2019-09-11T03:49:43.842328Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.12827257, -0.50820625, -0.0323797 , -0.49744146,  1.47655254],\n",
       "       [-1.86064942,  1.47067894, -1.07098905, -0.06903328,  1.39029289],\n",
       "       [-0.25113084, -0.93021344,  1.81900584, -0.85037806, -0.51959092],\n",
       "       [-0.83086235,  0.55036267,  1.1242602 , -0.09267453,  0.43763645],\n",
       "       [-0.57602888,  1.27352951,  0.11596341, -1.3557155 ,  0.91528381]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random((5, 5))\n",
    "z = (z - z.mean()) / z.std()\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 23. 创建一个自定义的包含四个无符号字节（RGBA）的`dtype`来描述颜色"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:44.151349Z",
     "start_time": "2019-09-11T03:49:44.007290Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype([('r', 'u1'), ('g', 'u1'), ('b', 'u1'), ('a', 'u1')])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "color = np.dtype([(\"r\", np.ubyte, 1),\n",
    "                  (\"g\", np.ubyte, 1),\n",
    "                  (\"b\", np.ubyte, 1),\n",
    "                  (\"a\", np.ubyte, 1)])\n",
    "color"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 24. 5x3的矩阵与3x2的矩阵相乘"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:44.292114Z",
     "start_time": "2019-09-11T03:49:44.154087Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3., 3.],\n",
       "       [3., 3.],\n",
       "       [3., 3.],\n",
       "       [3., 3.],\n",
       "       [3., 3.]])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.dot(np.ones((5, 3)), np.ones((3, 2)))\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:44.720937Z",
     "start_time": "2019-09-11T03:49:44.295248Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3., 3.],\n",
       "       [3., 3.],\n",
       "       [3., 3.],\n",
       "       [3., 3.],\n",
       "       [3., 3.]])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 也可以使用操作符 @\n",
    "z = np.ones((5, 3)) @ np.ones((3, 2))\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 25. 给定一个一维数组，将值在3和8之间的数字变为其负数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:44.896203Z",
     "start_time": "2019-09-11T03:49:44.724897Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3, -4, -5, -6, -7,  8,  9])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(10)\n",
    "z[(z > 3) & (z < 8)] *= -1\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-07-27T01:07:27.112409Z",
     "start_time": "2019-07-27T01:07:27.108092Z"
    }
   },
   "source": [
    "#### 26. 下面脚本的输出是什么\n",
    "\n",
    "```python\n",
    "# Author: Jake VanderPlas\n",
    "\n",
    "print(sum(range(5),-1))\n",
    "from numpy import *\n",
    "print(sum(range(5),-1))\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:45.155778Z",
     "start_time": "2019-09-11T03:49:44.898578Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(range(5), -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里是使用Python内置的`sum`函数, 它把所有的参数都当作求和的一部分相加， 这里就是简单地将所有的数字相加，10 - 1 = 9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:45.291321Z",
     "start_time": "2019-09-11T03:49:45.158199Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sum(range(5), -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里使用的是Numpy中的`np.sum`， 这里的`-1`并非待加的数字，而是另外一个参数的值，代表多维数组在求和时各个轴求和的顺序。具体可以`help(np.sum)`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 27. `z`是整数组成的向量，判断下列表达式是否正确"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:45.543706Z",
     "start_time": "2019-09-11T03:49:45.294109Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:45.798091Z",
     "start_time": "2019-09-11T03:49:45.545682Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([        1,         1,         4,        27,       256,      3125,\n",
       "           46656,    823543,  16777216, 387420489])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1\n",
    "z ** z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "前面提到过， 对于数组之间的`**`等算术运算， 是元素一一对应进行运算的(element-wise), 如这里387420489，就等于9**9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:45.932367Z",
     "start_time": "2019-09-11T03:49:45.800271Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0,   1,   2,   4,   8,  16,  32,  64, 128, 256])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2\n",
    "2 << z >> 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本质上进行两次移位运算，也就是等于`(2 << z) >> 2`.下面将其拆开来看。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.076610Z",
     "start_time": "2019-09-11T03:49:45.935346Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([   2,    4,    8,   16,   32,   64,  128,  256,  512, 1024])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2 << z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "就是将2分别左移0， 1， 2， ...， 9位，得到的就是`2 << 0, 2<<1, ..., 2<<9`,如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.224939Z",
     "start_time": "2019-09-11T03:49:46.078951Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "part1 = [2 << i for i in range(10)]\n",
    "part1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到与`2 << z`的输出是一致的。\n",
    "\n",
    "之后就是进行右移位操作，不同之处在于，这里是对于数组`2 << z`中的每个元素进行右移位，分别右移2个位置。每个数值右移2代表对每个值`x`，取`x // 4`, 对`part1`继续处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.389122Z",
     "start_time": "2019-09-11T03:49:46.229727Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 4, 8, 16, 32, 64, 128, 256]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[i // 4 for i in part1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到其与`2 << z >> 2`的输出是一致的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.498522Z",
     "start_time": "2019-09-11T03:49:46.393716Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, False, False, False, False, False, False,\n",
       "       False])"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 3\n",
    "z <- z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里涉及的主要是优先级的问题，随便找个操作符，如`<`,通过`help(\"<\")`即可查看所有操作符的优先级，默认是从低优先级到高优先级。可以看到，`-1`相比`<`具有更高的优先级， 所以这里就等同于`z < (-z)`，测试如下"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.640865Z",
     "start_time": "2019-09-11T03:49:46.503033Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, False, False, False, False, False, False,\n",
       "       False])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z < (-z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.772525Z",
     "start_time": "2019-09-11T03:49:46.645842Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.+0.j, 0.+1.j, 0.+2.j, 0.+3.j, 0.+4.j, 0.+5.j, 0.+6.j, 0.+7.j,\n",
       "       0.+8.j, 0.+9.j])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 4\n",
    "1j * z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对复数的运算的支持"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:46.919464Z",
     "start_time": "2019-09-11T03:49:46.774950Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 5\n",
    "z/1/1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "也就是`(z/1)/1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 181,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:55:46.762027Z",
     "start_time": "2019-09-11T03:55:46.720423Z"
    }
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-181-856b68e674c4>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 6\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mz\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mz\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0mz\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"
     ]
    }
   ],
   "source": [
    "# 6\n",
    "z < z > z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里参考了下Python表达式的[文档](https://docs.python.org/2/reference/expressions.html#not-in),和[stackoverflow](https://stackoverflow.com/questions/18755059/is-abc-valid-python)\n",
    "找到\n",
    ">Formally, if `a, b, c, …, y, z` are expressions and `op1, op2, …, opN` are comparison operators, then a `op1 b op2 c ... y opN z` is equivalent to `a op1 b and b op2 c and ... y opN z`, except that each expression is evaluated at most once.\n",
    "\n",
    "就是说，在一个表达式里面进行连续比较的时候，如`x < y <= z`,首先是符合语法的，其等同于`x < y adn y <=z`, 只不过对于重复的元素（这里的`y`）只估计一次。所以我们在Python原生的`list`中进行上述`z`的运算是可以正常返回的，代码如下。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:47.198136Z",
     "start_time": "2019-09-11T03:49:47.057793Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1 = [1, 2]\n",
    "l1 < l1 > l1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:47.339436Z",
     "start_time": "2019-09-11T03:49:47.200844Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(l1 < l1) and (l1 > l1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因为`l1 < l1`和`l1 > l1`全部是`False`,所以其`and`也是`False`.但是对于我们的`z`，也就是`np.ndarray`类型的数据，情况就有所不同。\n",
    "\n",
    "这里`z < z > z`依旧是估计为`z < z and z > z`, 其中`z < z`与`z > z`都是可以正常返回的，且结果都是一个长度为`z.size()`的`array`， 元素全部是布尔值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:47.492307Z",
     "start_time": "2019-09-11T03:49:47.344000Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, False, False, False, False, False, False,\n",
       "       False])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z < z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:47.650527Z",
     "start_time": "2019-09-11T03:49:47.494732Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, False, False, False, False, False, False,\n",
       "       False])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z > z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "不可行的是两者之间的`and`。 因为在进行`and`操作时，Numpy无法确切地知道形如`array([False, False, ...])`的数组到底是估计为`False`，还是`True`， 因为这里有两种方法来定义一个数组的布尔值：其一是`ａｌｌ`，即所有的元素全是`Ｔｒｕｅ`才判定为`Ｔｒｕｅ`，否则为`Ｆａｌｓｅ`；　另外一种方法是`ａｎｙ`，　即只要数组中有一个`Ｔｒｕｅ`，我们就判定其为`Ｔｒｕｅ`, 否则判定为`Ｆａｌｓｅ`. 正是这种不确定性使得Numpy报错，并建议使用`any`或者`all`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 28. 下列表达式的结果是什么\n",
    "\n",
    "```python\n",
    "np.array(0) / np.array(0)\n",
    "np.array(0) // np.array(0)\n",
    "np.array([np.nan]).astype(int).astype(float)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:47.805505Z",
     "start_time": "2019-09-11T03:49:47.654163Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: RuntimeWarning: invalid value encountered in true_divide\n",
      "  \"\"\"Entry point for launching an IPython kernel.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "nan"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.array(0) / np.array(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "返回`nan`并带有警告说在进行真除(true_divide)的时候出现问题，即0做分母。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:47.957116Z",
     "start_time": "2019-09-11T03:49:47.809627Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in floor_divide\n",
      "  \"\"\"Entry point for launching an IPython kernel.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.array(0) // np.array(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-07-27T02:35:08.133001Z",
     "start_time": "2019-07-27T02:35:08.127942Z"
    }
   },
   "source": [
    "返回0, 并带有警告说在进行地板除(floor_divide)的时候出现问题，即0做分母。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:48.100772Z",
     "start_time": "2019-09-11T03:49:47.959090Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-9.22337204e+18])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.array([np.nan]).astype(int).astype(float)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 29. 舍入浮点数数组，使其尽可能远离0\n",
    "即-0.3， -0.5， -0.6等近似为-1，而非0； 0.3， 0.5， 0.6等近似为1，而非0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:48.316377Z",
     "start_time": "2019-09-11T03:49:48.104398Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-7.76242024, -5.15644074, -5.19760008,  4.24343511,  3.25711345,\n",
       "        4.83702175,  4.92154317, -9.77526978,  0.45551806, -9.95335581])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.uniform(-10, 10, 10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:49:48.447435Z",
     "start_time": "2019-09-11T03:49:48.321511Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ -8.,  -6.,  -6.,   5.,   4.,   5.,   5., -10.,   1., -10.])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.copysign(np.ceil(np.abs(z)), z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 30. 找到两个数组中相同的元素"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们首先考虑内置的函数，但是我们不知道是否有类似的函数，所以我们可以灵活使用`np.lookfor`来找出我们要的函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:35.878920Z",
     "start_time": "2019-09-11T03:51:35.861129Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Search results for 'common values'\n",
      "----------------------------------\n",
      "numpy.ma.intersect1d\n",
      "    Returns the unique elements common to both arrays.\n",
      "numpy.gcd\n",
      "    Returns the greatest common divisor of ``|x1|`` and ``|x2|``\n",
      "numpy.lcm\n",
      "    Returns the lowest common multiple of ``|x1|`` and ``|x2|``\n",
      "numpy.intersect1d\n",
      "    Find the intersection of two arrays.\n",
      "numpy.ma.common_fill_value\n",
      "    Return the common filling value of two masked arrays, if any.\n",
      "numpy.add\n",
      "    Add arguments element-wise.\n",
      "numpy.less\n",
      "    Return the truth value of (x1 < x2) element-wise.\n",
      "numpy.sign\n",
      "    Returns an element-wise indication of the sign of a number.\n",
      "numpy.sqrt\n",
      "    Return the non-negative square-root of an array, element-wise.\n",
      "numpy.choose\n",
      "    Construct an array from an index array and a set of arrays to choose from.\n",
      "numpy.einsum\n",
      "    einsum(subscripts, *operands, out=None, dtype=None, order='K',\n",
      "numpy.nditer\n",
      "    Efficient multi-dimensional iterator object to iterate over arrays.\n",
      "numpy.greater\n",
      "    Return the truth value of (x1 > x2) element-wise.\n",
      "numpy.nonzero\n",
      "    Return the indices of the elements that are non-zero.\n",
      "numpy.less_equal\n",
      "    Return the truth value of (x1 =< x2) element-wise.\n",
      "numpy.bitwise_not\n",
      "    Compute bit-wise inversion, or bit-wise NOT, element-wise.\n",
      "numpy.histogram2d\n",
      "    Compute the bi-dimensional histogram of two data samples.\n",
      "numpy.ma.add\n",
      "    Add arguments element-wise.\n",
      "numpy.ma.cov\n",
      "    Estimate the covariance matrix.\n",
      "numpy.ma.less\n",
      "    Return the truth value of (x1 < x2) element-wise.\n",
      "numpy.ma.sqrt\n",
      "    Return the non-negative square-root of an array, element-wise.\n",
      "numpy.greater_equal\n",
      "    Return the truth value of (x1 >= x2) element-wise.\n",
      "numpy.linalg.qr\n",
      "    Compute the qr factorization of a matrix.\n",
      "numpy.ma.greater\n",
      "    Return the truth value of (x1 > x2) element-wise.\n",
      "numpy.ma.nonzero\n",
      "    nonzero(self)\n",
      "numpy.ma.less_equal\n",
      "    Return the truth value of (x1 =< x2) element-wise.\n",
      "numpy.histogram_bin_edges\n",
      "    Function to calculate only the edges of the bins used by the `histogram` function.\n",
      "numpy.ma.greater_equal\n",
      "    Return the truth value of (x1 >= x2) element-wise."
     ]
    }
   ],
   "source": [
    "np.lookfor(\"common values\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们发现返回得到第一个函数`np.intersect1d`就是我们要找的，进一步查看其用法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:40.995799Z",
     "start_time": "2019-09-11T03:51:40.990885Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " intersect1d(ar1, ar2, assume_unique=False, return_indices=False)\n",
      "\n",
      "Find the intersection of two arrays.\n",
      "\n",
      "Return the sorted, unique values that are in both of the input arrays.\n",
      "\n",
      "Parameters\n",
      "----------\n",
      "ar1, ar2 : array_like\n",
      "    Input arrays. Will be flattened if not already 1D.\n",
      "assume_unique : bool\n",
      "    If True, the input arrays are both assumed to be unique, which\n",
      "    can speed up the calculation.  Default is False.\n",
      "return_indices : bool\n",
      "    If True, the indices which correspond to the intersection of the two\n",
      "    arrays are returned. The first instance of a value is used if there are\n",
      "    multiple. Default is False.\n",
      "\n",
      "    .. versionadded:: 1.15.0\n",
      "\n",
      "Returns\n",
      "-------\n",
      "intersect1d : ndarray\n",
      "    Sorted 1D array of common and unique elements.\n",
      "comm1 : ndarray\n",
      "    The indices of the first occurrences of the common values in `ar1`.\n",
      "    Only provided if `return_indices` is True.\n",
      "comm2 : ndarray\n",
      "    The indices of the first occurrences of the common values in `ar2`.\n",
      "    Only provided if `return_indices` is True.\n",
      "\n",
      "\n",
      "See Also\n",
      "--------\n",
      "numpy.lib.arraysetops : Module with a number of other functions for\n",
      "                        performing set operations on arrays.\n",
      "\n",
      "Examples\n",
      "--------\n",
      ">>> np.intersect1d([1, 3, 4, 3], [3, 1, 2, 1])\n",
      "array([1, 3])\n",
      "\n",
      "To intersect more than two arrays, use functools.reduce:\n",
      "\n",
      ">>> from functools import reduce\n",
      ">>> reduce(np.intersect1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))\n",
      "array([3])\n",
      "\n",
      "To return the indices of the values common to the input arrays\n",
      "along with the intersected values:\n",
      ">>> x = np.array([1, 1, 2, 3, 4])\n",
      ">>> y = np.array([2, 1, 4, 6])\n",
      ">>> xy, x_ind, y_ind = np.intersect1d(x, y, return_indices=True)\n",
      ">>> x_ind, y_ind\n",
      "(array([0, 2, 4]), array([1, 0, 2]))\n",
      ">>> xy, x[x_ind], y[y_ind]\n",
      "(array([1, 2, 4]), array([1, 2, 4]), array([1, 2, 4]))\n"
     ]
    }
   ],
   "source": [
    "np.info(np.intersect1d)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据文档就可以直接使用了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:41.354463Z",
     "start_time": "2019-09-11T03:51:41.348401Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4])"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z1 = np.arange(-5, 5)\n",
    "z2 = np.arange(10)\n",
    "np.intersect1d(z1, z2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 31. 如何忽视所有Numpy的警告（不推荐）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:41.656102Z",
     "start_time": "2019-09-11T03:51:41.649821Z"
    }
   },
   "outputs": [],
   "source": [
    "# 自杀模式启动:-)\n",
    "defaults = np.seterr(all=\"ignore\")\n",
    "Z = np.ones(1) / 0\n",
    "# 恢复理智\n",
    "_ = np.seterr(**defaults)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:41.813895Z",
     "start_time": "2019-09-11T03:51:41.809197Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:3: RuntimeWarning: divide by zero encountered in true_divide\n",
      "  This is separate from the ipykernel package so we can avoid doing imports until\n"
     ]
    }
   ],
   "source": [
    "# 也可以定义错误处理的细节\n",
    "with np.errstate(divide='warn'):\n",
    "    Z = np.ones(1) / 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 32. 下面的表达式会返回`True`吗\n",
    "```python\n",
    "np.sqrt(-1) == np.emath.sqrt(-1)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:42.163468Z",
     "start_time": "2019-09-11T03:51:42.156328Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(-1) == np.emath.sqrt(-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:42.336762Z",
     "start_time": "2019-09-11T03:51:42.331535Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(nan, 1j)"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(-1), np.emath.sqrt(-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 33. 如何获取昨天，今天，明天的日期"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:42.672912Z",
     "start_time": "2019-09-11T03:51:42.668480Z"
    }
   },
   "outputs": [],
   "source": [
    "yesterday = np.datetime64('today', 'D') - np.timedelta64(1, 'D')\n",
    "today     = np.datetime64('today', 'D')\n",
    "tomorrow  = np.datetime64('today', 'D') + np.timedelta64(1, 'D')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:42.842652Z",
     "start_time": "2019-09-11T03:51:42.837739Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(numpy.datetime64('2019-09-10'),\n",
       " numpy.datetime64('2019-09-11'),\n",
       " numpy.datetime64('2019-09-12'))"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "yesterday, today, tomorrow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 34. 如何获取2016年7月全部31天的日期"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:43.191384Z",
     "start_time": "2019-09-11T03:51:43.186292Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['2016-07-01', '2016-07-02', '2016-07-03', '2016-07-04',\n",
       "       '2016-07-05', '2016-07-06', '2016-07-07', '2016-07-08',\n",
       "       '2016-07-09', '2016-07-10', '2016-07-11', '2016-07-12',\n",
       "       '2016-07-13', '2016-07-14', '2016-07-15', '2016-07-16',\n",
       "       '2016-07-17', '2016-07-18', '2016-07-19', '2016-07-20',\n",
       "       '2016-07-21', '2016-07-22', '2016-07-23', '2016-07-24',\n",
       "       '2016-07-25', '2016-07-26', '2016-07-27', '2016-07-28',\n",
       "       '2016-07-29', '2016-07-30', '2016-07-31'], dtype='datetime64[D]')"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange('2016-07', '2016-08', dtype='datetime64[D]')\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 35. 如何以替换的方式（in place）计算$((A+B)*(-A/2))$（不通过复制）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:43.507968Z",
     "start_time": "2019-09-11T03:51:43.498421Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.5, -1.5, -1.5])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.ones(3)*1\n",
    "B = np.ones(3)*2\n",
    "C = np.ones(3)*3\n",
    "np.add(A,B,out=B)\n",
    "np.divide(A,2,out=A)\n",
    "np.negative(A,out=A)\n",
    "np.multiply(A,B,out=A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 36. 用5种方法提取随机数组中的整数部分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:43.817200Z",
     "start_time": "2019-09-11T03:51:43.812193Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5.07555068, 0.21193302, 4.33521758, 4.46313056, 2.38819989,\n",
       "       8.30245732, 7.44764177, 5.86479001, 4.92867853, 4.8735588 ])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.uniform(0, 10, 10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:43.986352Z",
     "start_time": "2019-09-11T03:51:43.980081Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5., 0., 4., 4., 2., 8., 7., 5., 4., 4.])"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1\n",
    "z - z % 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:44.149657Z",
     "start_time": "2019-09-11T03:51:44.144761Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5., 0., 4., 4., 2., 8., 7., 5., 4., 4.])"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2\n",
    "np.floor(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:44.320126Z",
     "start_time": "2019-09-11T03:51:44.314596Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5., 0., 4., 4., 2., 8., 7., 5., 4., 4.])"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 3\n",
    "np.ceil(z) - 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:44.482478Z",
     "start_time": "2019-09-11T03:51:44.475744Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 0, 4, 4, 2, 8, 7, 5, 4, 4])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 4\n",
    "z.astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:44.624822Z",
     "start_time": "2019-09-11T03:51:44.619832Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5., 0., 4., 4., 2., 8., 7., 5., 4., 4.])"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 5\n",
    "np.trunc(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 37. 创建一个5x5的矩阵，每行均为0到4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:44.951720Z",
     "start_time": "2019-09-11T03:51:44.945695Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 1., 2., 3., 4.],\n",
       "       [0., 1., 2., 3., 4.],\n",
       "       [0., 1., 2., 3., 4.],\n",
       "       [0., 1., 2., 3., 4.],\n",
       "       [0., 1., 2., 3., 4.]])"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1,答案的方法\n",
    "z = np.zeros((5, 5))\n",
    "z += np.arange(5)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:46.283905Z",
     "start_time": "2019-09-11T03:51:46.277012Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4],\n",
       "       [0, 1, 2, 3, 4]])"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2,利用tile\n",
    "z = np.tile(np.arange(5), (5, 1))\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 38. 现有一个可以生成10个整数的生成器函数，利用其建立一个数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:46.640162Z",
     "start_time": "2019-09-11T03:51:46.633687Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1, 答案的方法\n",
    "def gen():\n",
    "    for i in range(10):\n",
    "        yield i\n",
    "        \n",
    "z = np.fromiter(gen(), dtype=float, count=-1)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:46.812776Z",
     "start_time": "2019-09-11T03:51:46.806194Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2, 列表解析\n",
    "z = np.array([i for i in gen()])\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 39. 创建一个长度为10，范围从0到1的向量（不包括0，1）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:47.154888Z",
     "start_time": "2019-09-11T03:51:47.146592Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.09090909, 0.18181818, 0.27272727, 0.36363636, 0.45454545,\n",
       "       0.54545455, 0.63636364, 0.72727273, 0.81818182, 0.90909091])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.linspace(0, 1, 11, endpoint=False)[1:]\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 40. 创建一个长度为10的随机数组并排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:47.490900Z",
     "start_time": "2019-09-11T03:51:47.484981Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.2667407 , 0.6050111 , 0.75354372, 0.27058423, 0.52230328,\n",
       "       0.09832853, 0.71363667, 0.88404059, 0.56705442, 0.99448158])"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random(10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:47.669791Z",
     "start_time": "2019-09-11T03:51:47.664607Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.09832853, 0.2667407 , 0.27058423, 0.52230328, 0.56705442,\n",
       "       0.6050111 , 0.71363667, 0.75354372, 0.88404059, 0.99448158])"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.sort()\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 41. 对于长度较小的数组，如何更高效地求和（相对`np.sum`）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:51:48.026410Z",
     "start_time": "2019-09-11T03:51:48.018589Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.arange(10)\n",
    "np.add.reduce(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:00.877420Z",
     "start_time": "2019-09-11T03:51:48.181096Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.52 µs ± 26.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit np.add.reduce(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.156727Z",
     "start_time": "2019-09-11T03:52:00.880063Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.94 µs ± 299 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit np.sum(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到`np.add.reduce`此时差不多快上一倍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 42. 检查两个数组A， B是否相等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.166995Z",
     "start_time": "2019-09-11T03:52:04.160998Z"
    }
   },
   "outputs": [],
   "source": [
    "A = np.random.randint(0,2,5)\n",
    "B = np.random.randint(0,2,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.235821Z",
     "start_time": "2019-09-11T03:52:04.170559Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1， 已知A，B的shape相等\n",
    "# 存在容错，适用于浮点数的比较\n",
    "np.allclose(A, B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.335988Z",
     "start_time": "2019-09-11T03:52:04.239888Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2. 同时检查shape与数值\n",
    "# 要求数值完全相等\n",
    "np.array_equal(A, B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 43. 限制数组为不可变数组（read only）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.501154Z",
     "start_time": "2019-09-11T03:52:04.339002Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  C_CONTIGUOUS : True\n",
       "  F_CONTIGUOUS : True\n",
       "  OWNDATA : True\n",
       "  WRITEABLE : True\n",
       "  ALIGNED : True\n",
       "  WRITEBACKIFCOPY : False\n",
       "  UPDATEIFCOPY : False"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros(10)\n",
    "z.flags"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.600725Z",
     "start_time": "2019-09-11T03:52:04.503265Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  C_CONTIGUOUS : True\n",
       "  F_CONTIGUOUS : True\n",
       "  OWNDATA : True\n",
       "  WRITEABLE : False\n",
       "  ALIGNED : True\n",
       "  WRITEBACKIFCOPY : False\n",
       "  UPDATEIFCOPY : False"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.flags.writeable = False\n",
    "z.flags"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:04.696002Z",
     "start_time": "2019-09-11T03:52:04.603923Z"
    }
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "assignment destination is read-only",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-95-ba34f733b6cb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mz\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: assignment destination is read-only"
     ]
    }
   ],
   "source": [
    "z[0] = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 44. 给定10x2矩阵代表平面座标系中座标，将其转化为极座标系座标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:22.824274Z",
     "start_time": "2019-09-11T03:52:22.816167Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1.0191402 , 0.3789241 , 1.01760735, 0.28642266, 1.09696314,\n",
       "        0.35963712, 0.86915363, 0.91189768, 1.18794229, 0.97413596]),\n",
       " array([1.08779371, 0.93177059, 0.79171987, 1.50554416, 1.01316742,\n",
       "        0.34043887, 0.93478081, 1.23714664, 0.70362634, 1.29930594]))"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random((10, 2))\n",
    "x, y = z[:, 0], z[:, 1]\n",
    "r = np.sqrt(x**2 + y**2)\n",
    "theta = np.arctan2(y, x)\n",
    "r, theta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 45. 创建一个长度为10的随机向量，并将其中最大的数改为0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:23.674738Z",
     "start_time": "2019-09-11T03:52:23.669372Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.93864246, 0.74504455, 0.91073504, 0.23722471, 0.49496735,\n",
       "       0.80987834, 0.95456578, 0.63748325, 0.91084975, 0.69213675])"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random(10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:23.883407Z",
     "start_time": "2019-09-11T03:52:23.877332Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.93864246, 0.74504455, 0.91073504, 0.23722471, 0.49496735,\n",
       "       0.80987834, 0.        , 0.63748325, 0.91084975, 0.69213675])"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z[z.argmax()] = 0\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 46. 创建一个结构化的数组，其元素为x轴，y轴的座标，并覆盖[0,1]x[0, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:24.316270Z",
     "start_time": "2019-09-11T03:52:24.307396Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([[0.  , 0.25, 0.5 , 0.75, 1.  ],\n",
       "        [0.  , 0.25, 0.5 , 0.75, 1.  ],\n",
       "        [0.  , 0.25, 0.5 , 0.75, 1.  ],\n",
       "        [0.  , 0.25, 0.5 , 0.75, 1.  ],\n",
       "        [0.  , 0.25, 0.5 , 0.75, 1.  ]]),\n",
       " array([[0.  , 0.  , 0.  , 0.  , 0.  ],\n",
       "        [0.25, 0.25, 0.25, 0.25, 0.25],\n",
       "        [0.5 , 0.5 , 0.5 , 0.5 , 0.5 ],\n",
       "        [0.75, 0.75, 0.75, 0.75, 0.75],\n",
       "        [1.  , 1.  , 1.  , 1.  , 1.  ]])]"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros((5, 5), [('x', float), ('y', float)])\n",
    "z = np.meshgrid(np.linspace(0, 1, 5),\n",
    "                np.linspace(0, 1, 5))\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 47. 给定两个数组X，Y， 计算其柯西矩阵C(Cauchy Matrix)并求其行列式\n",
    "$$C_{ij} = \\frac{1}{x_i-y_j}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:24.716992Z",
     "start_time": "2019-09-11T03:52:24.707099Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.5, -1.5, -2.5, -3.5, -4.5, -5.5, -6.5, -7.5],\n",
       "       [ 0.5, -0.5, -1.5, -2.5, -3.5, -4.5, -5.5, -6.5],\n",
       "       [ 1.5,  0.5, -0.5, -1.5, -2.5, -3.5, -4.5, -5.5],\n",
       "       [ 2.5,  1.5,  0.5, -0.5, -1.5, -2.5, -3.5, -4.5],\n",
       "       [ 3.5,  2.5,  1.5,  0.5, -0.5, -1.5, -2.5, -3.5],\n",
       "       [ 4.5,  3.5,  2.5,  1.5,  0.5, -0.5, -1.5, -2.5],\n",
       "       [ 5.5,  4.5,  3.5,  2.5,  1.5,  0.5, -0.5, -1.5],\n",
       "       [ 6.5,  5.5,  4.5,  3.5,  2.5,  1.5,  0.5, -0.5]])"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.arange(8)\n",
    "y = x + 0.5\n",
    "C = np.subtract.outer(x, y)\n",
    "C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:24.997212Z",
     "start_time": "2019-09-11T03:52:24.910147Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.8457040860738383e-92"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.det(C)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其实这里`np.subtract.outer`就等于进行了broadcast,我们也可以像下面这样写。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:25.318932Z",
     "start_time": "2019-09-11T03:52:25.311594Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.5, -1.5, -2.5, -3.5, -4.5, -5.5, -6.5, -7.5],\n",
       "       [ 0.5, -0.5, -1.5, -2.5, -3.5, -4.5, -5.5, -6.5],\n",
       "       [ 1.5,  0.5, -0.5, -1.5, -2.5, -3.5, -4.5, -5.5],\n",
       "       [ 2.5,  1.5,  0.5, -0.5, -1.5, -2.5, -3.5, -4.5],\n",
       "       [ 3.5,  2.5,  1.5,  0.5, -0.5, -1.5, -2.5, -3.5],\n",
       "       [ 4.5,  3.5,  2.5,  1.5,  0.5, -0.5, -1.5, -2.5],\n",
       "       [ 5.5,  4.5,  3.5,  2.5,  1.5,  0.5, -0.5, -1.5],\n",
       "       [ 6.5,  5.5,  4.5,  3.5,  2.5,  1.5,  0.5, -0.5]])"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C_test = x.reshape(8, 1)- y.reshape(1, 8)\n",
    "C_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:25.528199Z",
     "start_time": "2019-09-11T03:52:25.523627Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.8457040860738383e-92"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.det(C_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:25.730275Z",
     "start_time": "2019-09-11T03:52:25.724044Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试两种方法返回的C是否相同\n",
    "np.array_equal(C, C_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 48. 打印Numpy所有标量类型(scalar type)可表示的最值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:26.143308Z",
     "start_time": "2019-09-11T03:52:26.136136Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.int8'>: min=-128, max=127\n",
      "<class 'numpy.int16'>: min=-32768, max=32767\n",
      "<class 'numpy.int32'>: min=-2147483648, max=2147483647\n",
      "<class 'numpy.int64'>: min=-9223372036854775808, max=9223372036854775807\n",
      "<class 'numpy.float16'>: min=-65504.0, max=65504.0\n",
      "<class 'numpy.float32'>: min=-3.4028234663852886e+38, max=3.4028234663852886e+38\n",
      "<class 'numpy.float64'>: min=-1.7976931348623157e+308, max=1.7976931348623157e+308\n",
      "<class 'numpy.float128'>: min=-inf, max=inf\n"
     ]
    }
   ],
   "source": [
    "for dtype in [np.int8, np.int16, np.int32, np.int64]:\n",
    "    info = np.iinfo(dtype)\n",
    "    print(f\"{dtype}: min={info.min}, max={info.max}\")\n",
    "for dtype in [np.float16, np.float32, np.float64, np.float128]:\n",
    "    info = np.finfo(dtype)\n",
    "    print(f\"{dtype}: min={info.min}, max={info.max}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 49. 打印数组所有元素（不省略）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:26.542789Z",
     "start_time": "2019-09-11T03:52:26.536988Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "with np.printoptions(threshold=np.inf):\n",
    "    z = np.ones((10, 10))\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 50. 给定一个数，在数组中找出距离其最近的数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:26.995597Z",
     "start_time": "2019-09-11T03:52:26.990148Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.04294299, 0.8335869 , 0.36994852, 0.936557  , 0.48305288,\n",
       "       0.12533161, 0.96445418, 0.01702583, 0.67657077, 0.14043997])"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 给定的数组\n",
    "z = np.random.uniform(0, 1, 10)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:27.706837Z",
     "start_time": "2019-09-11T03:52:27.701593Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.48305287517652307"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 给定的数\n",
    "x = 0.5\n",
    "# 定位距离最近数的位置\n",
    "index = np.abs(z - x).argmin()\n",
    "# 找到该数字\n",
    "z[index]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 51. 创建一个结构化的数组，其元素为一个座标(x,y)和一个颜色参数(r,g,b)\n",
    "和46题类似。\n",
    ">另外，这可以是一个像素点的表示方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:28.150008Z",
     "start_time": "2019-09-11T03:52:28.136122Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([((0., 0.), (0., 0., 0.)), ((0., 0.), (0., 0., 0.)),\n",
       "       ((0., 0.), (0., 0., 0.)), ((0., 0.), (0., 0., 0.)),\n",
       "       ((0., 0.), (0., 0., 0.)), ((0., 0.), (0., 0., 0.)),\n",
       "       ((0., 0.), (0., 0., 0.)), ((0., 0.), (0., 0., 0.)),\n",
       "       ((0., 0.), (0., 0., 0.)), ((0., 0.), (0., 0., 0.))],\n",
       "      dtype=[('position', [('x', '<f8'), ('y', '<f8')]), ('color', [('r', '<f8'), ('g', '<f8'), ('b', '<f8')])])"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros(10, [('position', [('x', float, 1),\n",
    "                               ('y', float, 1)]),\n",
    "                 ('color', [('r', float, 1),\n",
    "                            ('g', float, 1),\n",
    "                            ('b', float, 1)])\n",
    "                 ]\n",
    "            )\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 52. 考虑一个形状为（10， 2）的随机向量，若其代表二维平面中的点，求各点之间的距离"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:28.925915Z",
     "start_time": "2019-09-11T03:52:28.914012Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.        , 0.82757935, 0.64681519, 0.43368238, 0.85165766,\n",
       "        0.57613768, 0.48566732, 0.44501945, 0.90701745, 0.55962651],\n",
       "       [0.82757935, 0.        , 0.3477681 , 0.96918723, 0.67596378,\n",
       "        0.71128017, 0.37897508, 0.43258791, 0.50371629, 0.26882844],\n",
       "       [0.64681519, 0.3477681 , 0.        , 0.65720606, 0.37061334,\n",
       "        0.36563979, 0.18181895, 0.43879256, 0.29206274, 0.27712044],\n",
       "       [0.43368238, 0.96918723, 0.65720606, 0.        , 0.64632996,\n",
       "        0.35301865, 0.59527913, 0.73887741, 0.80043261, 0.74933684],\n",
       "       [0.85165766, 0.67596378, 0.37061334, 0.64632996, 0.        ,\n",
       "        0.30214225, 0.51433777, 0.78889208, 0.22248961, 0.6454205 ],\n",
       "       [0.57613768, 0.71128017, 0.36563979, 0.35301865, 0.30214225,\n",
       "        0.        , 0.39640111, 0.64228203, 0.44903039, 0.56316235],\n",
       "       [0.48566732, 0.37897508, 0.18181895, 0.59527913, 0.51433777,\n",
       "        0.39640111, 0.        , 0.274627  , 0.47255738, 0.1680208 ],\n",
       "       [0.44501945, 0.43258791, 0.43879256, 0.73887741, 0.78889208,\n",
       "        0.64228203, 0.274627  , 0.        , 0.72766324, 0.18906137],\n",
       "       [0.90701745, 0.50371629, 0.29206274, 0.80043261, 0.22248961,\n",
       "        0.44903039, 0.47255738, 0.72766324, 0.        , 0.55335753],\n",
       "       [0.55962651, 0.26882844, 0.27712044, 0.74933684, 0.6454205 ,\n",
       "        0.56316235, 0.1680208 , 0.18906137, 0.55335753, 0.        ]])"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.random((10, 2))\n",
    "x, y = np.atleast_2d(z[:, 0], z[:, 1])\n",
    "d = np.sqrt((x - x.T)**2 + (y - y.T)**2)\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里使用`np.atleast_2d`使得我们得到的`x`， `y`直接就是2维的数组，方便了我们后面直接使用`broadcasting`.我们也可以采用下面的方法代替这行，但是不够简洁：\n",
    "```python\n",
    "x = z[:, 0].reshape(10, 1)\n",
    "y = z[:, 1].reshape(1, 10)\n",
    "```\n",
    "\n",
    "此外我们也可以使用`scipy`内置的函数，其效率要高一些。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:30.352754Z",
     "start_time": "2019-09-11T03:52:29.400534Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.        , 0.82757935, 0.64681519, 0.43368238, 0.85165766,\n",
       "        0.57613768, 0.48566732, 0.44501945, 0.90701745, 0.55962651],\n",
       "       [0.82757935, 0.        , 0.3477681 , 0.96918723, 0.67596378,\n",
       "        0.71128017, 0.37897508, 0.43258791, 0.50371629, 0.26882844],\n",
       "       [0.64681519, 0.3477681 , 0.        , 0.65720606, 0.37061334,\n",
       "        0.36563979, 0.18181895, 0.43879256, 0.29206274, 0.27712044],\n",
       "       [0.43368238, 0.96918723, 0.65720606, 0.        , 0.64632996,\n",
       "        0.35301865, 0.59527913, 0.73887741, 0.80043261, 0.74933684],\n",
       "       [0.85165766, 0.67596378, 0.37061334, 0.64632996, 0.        ,\n",
       "        0.30214225, 0.51433777, 0.78889208, 0.22248961, 0.6454205 ],\n",
       "       [0.57613768, 0.71128017, 0.36563979, 0.35301865, 0.30214225,\n",
       "        0.        , 0.39640111, 0.64228203, 0.44903039, 0.56316235],\n",
       "       [0.48566732, 0.37897508, 0.18181895, 0.59527913, 0.51433777,\n",
       "        0.39640111, 0.        , 0.274627  , 0.47255738, 0.1680208 ],\n",
       "       [0.44501945, 0.43258791, 0.43879256, 0.73887741, 0.78889208,\n",
       "        0.64228203, 0.274627  , 0.        , 0.72766324, 0.18906137],\n",
       "       [0.90701745, 0.50371629, 0.29206274, 0.80043261, 0.22248961,\n",
       "        0.44903039, 0.47255738, 0.72766324, 0.        , 0.55335753],\n",
       "       [0.55962651, 0.26882844, 0.27712044, 0.74933684, 0.6454205 ,\n",
       "        0.56316235, 0.1680208 , 0.18906137, 0.55335753, 0.        ]])"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import scipy\n",
    "import scipy.spatial\n",
    "\n",
    "d = scipy.spatial.distance.cdist(z, z)\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 53. 将一个32位的浮点数数组，（不使用额外内存）转化为32为的整数数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:30.364185Z",
     "start_time": "2019-09-11T03:52:30.356545Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.zeros(10, dtype=np.float32)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:30.625589Z",
     "start_time": "2019-09-11T03:52:30.619815Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32)"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = z.astype(np.int32, copy=False)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 54. 如何读取下面的文件\n",
    "```\n",
    "1, 2, 3, 4, 5\n",
    "6,  ,  , 7, 8\n",
    " ,  , 9,10,11\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:31.112303Z",
     "start_time": "2019-09-11T03:52:31.106075Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.,  2.,  3.,  4.,  5.],\n",
       "       [ 6., nan, nan,  7.,  8.],\n",
       "       [nan, nan,  9., 10., 11.]])"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from io import StringIO\n",
    "# “假”的文件\n",
    "s = StringIO(\"\"\"1, 2, 3, 4, 5\\n\n",
    "                6,  ,  , 7, 8\\n\n",
    "                 ,  , 9,10,11\\n\"\"\")\n",
    "z = np.genfromtxt(s, delimiter=\",\", missing_values=' ')\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 55. Python内置有`enumerate`,Numpy中与之对应的是？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:31.612857Z",
     "start_time": "2019-09-11T03:52:31.605578Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 0) 0\n",
      "(0, 1) 1\n",
      "(0, 2) 2\n",
      "(1, 0) 3\n",
      "(1, 1) 4\n",
      "(1, 2) 5\n",
      "(2, 0) 6\n",
      "(2, 1) 7\n",
      "(2, 2) 8\n"
     ]
    }
   ],
   "source": [
    "Z = np.arange(9).reshape(3,3)\n",
    "for index, value in np.ndenumerate(Z):\n",
    "    print(index, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:31.831383Z",
     "start_time": "2019-09-11T03:52:31.822861Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 0) 0\n",
      "(0, 1) 1\n",
      "(0, 2) 2\n",
      "(1, 0) 3\n",
      "(1, 1) 4\n",
      "(1, 2) 5\n",
      "(2, 0) 6\n",
      "(2, 1) 7\n",
      "(2, 2) 8\n"
     ]
    }
   ],
   "source": [
    "for index in np.ndindex(Z.shape):\n",
    "    print(index, Z[index])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 56. 生成二维高斯分布"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:32.336509Z",
     "start_time": "2019-09-11T03:52:32.327741Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.36787944, 0.44822088, 0.51979489, 0.57375342, 0.60279818,\n",
       "        0.60279818, 0.57375342, 0.51979489, 0.44822088, 0.36787944],\n",
       "       [0.44822088, 0.54610814, 0.63331324, 0.69905581, 0.73444367,\n",
       "        0.73444367, 0.69905581, 0.63331324, 0.54610814, 0.44822088],\n",
       "       [0.51979489, 0.63331324, 0.73444367, 0.81068432, 0.85172308,\n",
       "        0.85172308, 0.81068432, 0.73444367, 0.63331324, 0.51979489],\n",
       "       [0.57375342, 0.69905581, 0.81068432, 0.89483932, 0.9401382 ,\n",
       "        0.9401382 , 0.89483932, 0.81068432, 0.69905581, 0.57375342],\n",
       "       [0.60279818, 0.73444367, 0.85172308, 0.9401382 , 0.98773022,\n",
       "        0.98773022, 0.9401382 , 0.85172308, 0.73444367, 0.60279818],\n",
       "       [0.60279818, 0.73444367, 0.85172308, 0.9401382 , 0.98773022,\n",
       "        0.98773022, 0.9401382 , 0.85172308, 0.73444367, 0.60279818],\n",
       "       [0.57375342, 0.69905581, 0.81068432, 0.89483932, 0.9401382 ,\n",
       "        0.9401382 , 0.89483932, 0.81068432, 0.69905581, 0.57375342],\n",
       "       [0.51979489, 0.63331324, 0.73444367, 0.81068432, 0.85172308,\n",
       "        0.85172308, 0.81068432, 0.73444367, 0.63331324, 0.51979489],\n",
       "       [0.44822088, 0.54610814, 0.63331324, 0.69905581, 0.73444367,\n",
       "        0.73444367, 0.69905581, 0.63331324, 0.54610814, 0.44822088],\n",
       "       [0.36787944, 0.44822088, 0.51979489, 0.57375342, 0.60279818,\n",
       "        0.60279818, 0.57375342, 0.51979489, 0.44822088, 0.36787944]])"
      ]
     },
     "execution_count": 117,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X, Y = np.meshgrid(np.linspace(-1,1,10), np.linspace(-1,1,10))\n",
    "D = np.sqrt(X*X+Y*Y)\n",
    "sigma, mu = 1.0, 0.0\n",
    "G = np.exp(-( (D-mu)**2 / ( 2.0 * sigma**2 ) ) )\n",
    "G"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 57. 随机地在二维数组中放置p个元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:32.784580Z",
     "start_time": "2019-09-11T03:52:32.774978Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0.],\n",
       "       [1., 0., 1., 0., 1.],\n",
       "       [0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n = 5\n",
    "p = 3\n",
    "z = np.zeros((n, n))\n",
    "np.put(z, np.random.choice(range(n*n), p), 1)\n",
    "z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 58. 矩阵每行进行中心化（减去均值）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:33.193960Z",
     "start_time": "2019-09-11T03:52:33.189268Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2, 3, 4],\n",
       "       [5, 6, 7, 8, 9]])"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1, 答案的方法\n",
    "z = np.arange(10).reshape(2, 5)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:33.405321Z",
     "start_time": "2019-09-11T03:52:33.399442Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-2., -1.,  0.,  1.,  2.],\n",
       "       [-2., -1.,  0.,  1.,  2.]])"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z_new = z - z.mean(axis=1, keepdims=True)\n",
    "z_new"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意这里，设置`keepdims`可以方便进行`broadcasting`, 免去手动`reshape`的流程。\n",
    "\n",
    "我们也可以考虑对矩阵每一行应用一个中心化的函数来完成任务。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:33.810856Z",
     "start_time": "2019-09-11T03:52:33.804195Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-2., -1.,  0.,  1.,  2.],\n",
       "       [-2., -1.,  0.,  1.,  2.]])"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2, apply方法\n",
    "def centered(xs):\n",
    "    return xs - xs.mean()\n",
    "\n",
    "z_new = np.apply_along_axis(centered, 1, z)\n",
    "z_new"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 59. 根据某列数据来排列数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:34.527476Z",
     "start_time": "2019-09-11T03:52:34.520053Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[9, 0, 7],\n",
       "       [8, 4, 6],\n",
       "       [5, 7, 5]])"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.randint(0, 10, (3, 3))\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:34.734451Z",
     "start_time": "2019-09-11T03:52:34.728139Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[9, 0, 7],\n",
       "       [8, 4, 6],\n",
       "       [5, 7, 5]])"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 根据第二列顺序排列\n",
    "z[z[:, 1].argsort(), ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 60. 判断二维数组是否含有空列(全为0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:35.178889Z",
     "start_time": "2019-09-11T03:52:35.171232Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 2, 1, 2, 0, 0, 1, 2, 2],\n",
       "       [2, 0, 2, 2, 2, 1, 2, 0, 0, 0],\n",
       "       [0, 1, 0, 1, 1, 2, 1, 0, 0, 2]])"
      ]
     },
     "execution_count": 124,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.random.randint(0, 3, (3, 10))\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:35.377928Z",
     "start_time": "2019-09-11T03:52:35.373928Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "print((~z.any(axis=0)).any())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "一旦有空列的时候， `z.any(axis=0)`返回`False`， 即`~z.any(axis=0)`返回`True`， 之后再应用`any`, 则比返回`True`。 反之，若无任何空列，`~z.any(axis=0)`全部返回`False`， 应用`any`，依旧返回`False`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 61. 给定一个数，在数组中找出距离其最近的数\n",
    "与50题重复."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 62. 考虑两个数组，形状分别是（3， 1）， （1， 3），如何使用迭代器将其相加？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:36.136940Z",
     "start_time": "2019-09-11T03:52:36.131680Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2]\n",
      " [1 2 3]\n",
      " [2 3 4]]\n"
     ]
    }
   ],
   "source": [
    "A = np.arange(3).reshape(3,1)\n",
    "B = np.arange(3).reshape(1,3)\n",
    "it = np.nditer([A,B,None])\n",
    "for x,y,z in it: z[...] = x + y\n",
    "print(it.operands[2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 63. 创建一个带有名称属性的数组类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:36.832242Z",
     "start_time": "2019-09-11T03:52:36.826046Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "range_10\n"
     ]
    }
   ],
   "source": [
    "class NamedArray(np.ndarray):\n",
    "    def __new__(cls, array, name=\"no name\"):\n",
    "        obj = np.asarray(array).view(cls)\n",
    "        obj.name = name\n",
    "        return obj\n",
    "    def __array_finalize__(self, obj):\n",
    "        if obj is None: return\n",
    "        self.info = getattr(obj, 'name', \"no name\")\n",
    "\n",
    "Z = NamedArray(np.arange(10), \"range_10\")\n",
    "print (Z.name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 64. 给定一个数值向量，和一个索引向量，根据后者的索引，在前者对应位置加1（注意重复索引）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:37.201952Z",
     "start_time": "2019-09-11T03:52:37.193164Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2., 2., 6., 5., 2., 3., 3., 3., 3., 1.])"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Author: Brett Olsen\n",
    "Z = np.ones(10)\n",
    "I = np.random.randint(0,len(Z),20)\n",
    "\n",
    "Z_new = Z + np.bincount(I, minlength=len(Z))\n",
    "Z_new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:37.381065Z",
     "start_time": "2019-09-11T03:52:37.374801Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2., 2., 6., 5., 2., 3., 3., 3., 3., 1.])"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Another solution\n",
    "# Author: Bartosz Telenczuk\n",
    "np.add.at(Z, I, 1)\n",
    "Z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 65. 根据索引列表I，对数值列表X进行累加，得到F"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:38.185038Z",
     "start_time": "2019-09-11T03:52:38.179403Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 7. 0. 6. 5. 0. 0. 0. 0. 3.]\n"
     ]
    }
   ],
   "source": [
    "X = [1,2,3,4,5,6]\n",
    "I = [1,3,9,3,4,1]\n",
    "F = np.bincount(I,X)\n",
    "print(F)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里`bincount`的用法有点绕...让我们举个例子先:-)\n",
    "\n",
    "我们把`I`中出现的数字比作个人的银行账户编号，可以看到这里最大的编号为9，所以我们暂时可以只考虑编号0~9的账户情况， 这10个账户，正好对应最后得到F的10个位置。进一步地，`I`与`X`结合，可以看作这些银行账户交易的流水，其中`I`为账户编号，`X`为对应的金额。比如，因为`I[0]=1`，我们知道是账户1发生交易，对应的`X[0]=1`，所以账户1的金额要加1；此外账户1还发生一次交易（`I[5]=1`）, 对应的金额`X[5] = 6`，所以这段时间账户1总的金额就是`6 + 1 = 7`，所以得到`F[1] = 7`.\n",
    "\n",
    "简言之，我们的任务就是根据`X`和`I`组成的交易流水，来计算各个账户总的金额。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 66. 给定一张照片（w, h, 3），计算其中不同颜色的个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:38.749155Z",
     "start_time": "2019-09-11T03:52:38.744103Z"
    }
   },
   "outputs": [],
   "source": [
    "# Author: Nadav Horesh\n",
    "\n",
    "w,h = 16, 16\n",
    "I = np.random.randint(0,2,(h,w,3)).astype(np.ubyte)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:39.196490Z",
     "start_time": "2019-09-11T03:52:39.189338Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8\n"
     ]
    }
   ],
   "source": [
    "# 注意我们这里必须先乘256*256，否则会爆栈 \n",
    "F = I[...,0]*(256*256) + I[...,1]*256 +I[...,2]\n",
    "n = len(np.unique(F))\n",
    "print(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 67. 考虑一个四维数组，计算后两个轴上的元素和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:39.592580Z",
     "start_time": "2019-09-11T03:52:39.586950Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[52, 44, 44, 68],\n",
       "       [61, 60, 44, 53],\n",
       "       [42, 66, 72, 57]])"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.random.randint(0,10,(3,4,3,4))\n",
    "A.sum(axis=(-2,-1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 68. 给定向量D，根据索引数组S得到子集，计算子集上的均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:40.202176Z",
     "start_time": "2019-09-11T03:52:40.193964Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.58150261 0.55134568 0.57372635 0.46632861 0.51824552 0.5358013\n",
      " 0.42991891 0.46169025 0.39369914 0.44701464]\n"
     ]
    }
   ],
   "source": [
    "D = np.random.uniform(0,1,100)\n",
    "S = np.random.randint(0,10,100)\n",
    "D_sums = np.bincount(S, weights=D)\n",
    "D_counts = np.bincount(S)\n",
    "D_means = D_sums / D_counts\n",
    "print(D_means)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "结合65题给出的例子，在那里是根据流水计算各个账户总的金额，这里是计算各个账户每次交易的平均金额，也就是该账户总的金额除以其交易的次数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 69. 获取矩阵点乘(dot product)结果的对角线元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:40.970004Z",
     "start_time": "2019-09-11T03:52:40.963259Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.27203858, 1.95734402, 1.1140674 , 1.32168438, 0.85313171])"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Author: Mathieu Blondel\n",
    "\n",
    "A = np.random.uniform(0,1,(5,5))\n",
    "B = np.random.uniform(0,1,(5,5))\n",
    "\n",
    "# 慢的版本\n",
    "np.diag(np.dot(A, B))\n",
    "\n",
    "# 快的版本\n",
    "np.sum(A * B.T, axis=1)\n",
    "\n",
    "# 更快的版本\n",
    "np.einsum(\"ij,ji->i\", A, B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 70. 如何在数组[1, 2, 3, 4, 5]每两个值的中间添加三个0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:41.396754Z",
     "start_time": "2019-09-11T03:52:41.390102Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 0., 0., 0., 2., 0., 0., 0., 3., 0., 0., 0., 4., 0., 0., 0., 5.])"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = np.array([1, 2, 3, 4, 5])\n",
    "nz = 3  # 0的个数\n",
    "v = np.zeros(len(z) + nz*(len(z)-1))\n",
    "v[::nz+1] = z\n",
    "v"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 71. 维度分别为（5， 5， 3）， （5， 5）的两个数组相乘"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:42.190547Z",
     "start_time": "2019-09-11T03:52:42.184933Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]]\n",
      "\n",
      " [[2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]]\n",
      "\n",
      " [[2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]]\n",
      "\n",
      " [[2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]]\n",
      "\n",
      " [[2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]\n",
      "  [2. 2. 2.]]]\n"
     ]
    }
   ],
   "source": [
    "A = np.ones((5,5,3))\n",
    "B = 2*np.ones((5,5))\n",
    "print(A * B[:,:,None])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 72. 交换数组的两行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:42.592901Z",
     "start_time": "2019-09-11T03:52:42.585652Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14],\n",
       "       [15, 16, 17, 18, 19],\n",
       "       [20, 21, 22, 23, 24]])"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.arange(25).reshape((5, 5))\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:42.770106Z",
     "start_time": "2019-09-11T03:52:42.764250Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5,  6,  7,  8,  9],\n",
       "       [ 0,  1,  2,  3,  4],\n",
       "       [10, 11, 12, 13, 14],\n",
       "       [15, 16, 17, 18, 19],\n",
       "       [20, 21, 22, 23, 24]])"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 交换第一、二两行\n",
    "A[[0, 1]] = A[[1, 0]]\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 73. 给定10个三元组描述10个三角形，找出所有边的集合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:43.126543Z",
     "start_time": "2019-09-11T03:52:43.120300Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[( 6, 31) ( 6, 96) ( 7, 30) ( 7, 82) (11, 18) (11, 48) (15, 28) (18, 48)\n",
      " (24, 29) (24, 65) (25, 51) (25, 84) (28, 28) (29, 32) (29, 65) (30, 82)\n",
      " (31, 96) (32, 65) (43, 77) (43, 88) (46, 54) (46, 71) (51, 84) (54, 71)\n",
      " (68, 83) (68, 89) (77, 88) (83, 89)]\n"
     ]
    }
   ],
   "source": [
    "faces = np.random.randint(0,100,(10,3))\n",
    "F = np.roll(faces.repeat(2,axis=1),-1,axis=1)\n",
    "F = F.reshape(len(F)*3,2)\n",
    "F = np.sort(F,axis=1)\n",
    "G = F.view( dtype=[('p0',F.dtype),('p1',F.dtype)] )\n",
    "G = np.unique(G)\n",
    "print(G)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感觉这里的方法比较巧妙，可以将每一步拆解来理解怎么将每条边抽取出来。之后比较细节的地方就是对描述“边”的二元组排序(如果不排序，后面比较的时候就会出现(a, b)与（b, a）不是同一条边的错误判断)，之后通过`view`转化类型，方便比较（使用`np.unique`）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 74. 给定A，我们有C = np.bincount(A), 那么，给定C，如何找到对应的A？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:44.134652Z",
     "start_time": "2019-09-11T03:52:44.127862Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 1 2 3 4 4 6]\n"
     ]
    }
   ],
   "source": [
    "C = np.bincount([1,1,2,3,4,4,6])\n",
    "A = np.repeat(np.arange(len(C)), C)\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 75. 用滑动窗口计算平均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:44.494391Z",
     "start_time": "2019-09-11T03:52:44.488474Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15. 16. 17. 18.]\n"
     ]
    }
   ],
   "source": [
    "def moving_average(a, n=3) :\n",
    "    ret = np.cumsum(a, dtype=float)\n",
    "    ret[n:] = ret[n:] - ret[:-n]\n",
    "    return ret[n - 1:] / n\n",
    "Z = np.arange(20)\n",
    "print(moving_average(Z, n=3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 76. 给定一个一维数组，组建一个二维数组，使得第一行为Z[0], Z[1], Z[2], 第二行为Z[1], Z[2], Z[3], 依此类推，最后一行为Z[-3], Z[-2], Z[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:45.038677Z",
     "start_time": "2019-09-11T03:52:45.032871Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2]\n",
      " [1 2 3]\n",
      " [2 3 4]\n",
      " [3 4 5]\n",
      " [4 5 6]\n",
      " [5 6 7]\n",
      " [6 7 8]\n",
      " [7 8 9]]\n"
     ]
    }
   ],
   "source": [
    "from numpy.lib import stride_tricks\n",
    "\n",
    "def rolling(a, window):\n",
    "    shape = (a.size - window + 1, window)\n",
    "    strides = (a.itemsize, a.itemsize)\n",
    "    return stride_tricks.as_strided(a, shape=shape, strides=strides)\n",
    "Z = rolling(np.arange(10), 3)\n",
    "print(Z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 77. 如何原地对布尔值取反，如何原地改变数字的正负"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:45.395912Z",
     "start_time": "2019-09-11T03:52:45.388497Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.73959528,  0.74138049, -0.94811162, -0.50843124, -0.83335491,\n",
       "        0.92459432,  0.42830231, -0.64581576,  0.45053274,  0.8965521 ,\n",
       "        0.70411344,  0.96701466, -0.56483325,  0.30175679, -0.49935569,\n",
       "        0.89009322,  0.84360355, -0.57868105,  0.25912389,  0.77807512,\n",
       "        0.18956795, -0.30259756,  0.12742359,  0.5950497 ,  0.11222084,\n",
       "       -0.48429619,  0.80796982, -0.02344253, -0.68723289, -0.9870873 ,\n",
       "       -0.26151235,  0.42905334,  0.74795648,  0.97328859,  0.32368876,\n",
       "        0.03135965, -0.09238209,  0.92792125,  0.8775511 ,  0.95367849,\n",
       "       -0.01477888,  0.46681795,  0.10938847, -0.94721852, -0.59555263,\n",
       "        0.43174897, -0.11157278,  0.60482401, -0.58120172,  0.82476071,\n",
       "       -0.67585093,  0.51747489,  0.13147537,  0.14427685,  0.79576564,\n",
       "       -0.81762747,  0.70197738, -0.81513605,  0.97909284,  0.65293123,\n",
       "       -0.67827731,  0.37949073, -0.69797135, -0.8226879 , -0.79980223,\n",
       "       -0.73445726, -0.67552438,  0.49271431, -0.68601626, -0.23525618,\n",
       "       -0.96835393, -0.22108029, -0.30339673, -0.30893032, -0.10465462,\n",
       "        0.6285398 , -0.96195274,  0.80812673, -0.49652576, -0.04923682,\n",
       "        0.41848055,  0.54361849, -0.00747832, -0.86391432, -0.14825956,\n",
       "       -0.97948923,  0.14045395,  0.1672885 , -0.25575461, -0.81473666,\n",
       "        0.86115452, -0.10080629,  0.69078833, -0.4371216 ,  0.7291862 ,\n",
       "        0.99090707, -0.07503235,  0.9668144 , -0.07102907,  0.90861586])"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = np.random.randint(0,2,100)\n",
    "np.logical_not(Z, out=Z)\n",
    "\n",
    "Z = np.random.uniform(-1.0,1.0,100)\n",
    "np.negative(Z, out=Z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 78. 计算点p到各个直线i的距离, 其中直线由(P0[i]， P1[i])表示，P0，P1为一系列对应的点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:45.953537Z",
     "start_time": "2019-09-11T03:52:45.938787Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.01154163  5.12606935 13.94958511 22.07140895  0.94980679 11.10441586\n",
      " 10.13624982 15.90978826 12.76884591  7.35750952]\n"
     ]
    }
   ],
   "source": [
    "def distance(P0, P1, p):\n",
    "    T = P1 - P0\n",
    "    L = (T**2).sum(axis=1)\n",
    "    U = -((P0[:,0]-p[...,0])*T[:,0] + (P0[:,1]-p[...,1])*T[:,1]) / L\n",
    "    U = U.reshape(len(U),1)\n",
    "    D = P0 + U*T - p\n",
    "    return np.sqrt((D**2).sum(axis=1))\n",
    "\n",
    "P0 = np.random.uniform(-10,10,(10,2))\n",
    "P1 = np.random.uniform(-10,10,(10,2))\n",
    "p  = np.random.uniform(-10,10,( 1,2))\n",
    "print(distance(P0, P1, p))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 79. 接上题，如何计算P0中各点P0[j]到各直线（P0[i], P1[i]）的距离"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:46.320238Z",
     "start_time": "2019-09-11T03:52:46.312780Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 3.5734595   0.66180336  7.3187876   4.99413157  0.96165362  1.50776605\n",
      "  15.24621075  5.09372975  5.79926051  2.37223415]\n",
      " [ 9.65216196  3.90422416  0.02454316  5.90288419  6.93066482  5.33370707\n",
      "   4.85444051  7.35964798  7.41460408  6.10650993]\n",
      " [ 3.0170691   9.17194136  4.03658393  0.93905036 11.63440516  9.62787647\n",
      "   2.93837077  6.05884677 13.55270024  0.66358603]\n",
      " [ 6.64712401  9.12738601  5.142417    5.57297746 12.16615989 10.53392643\n",
      "   0.31688742 10.17275773 12.38143328  2.29469197]\n",
      " [ 1.29889259  9.25138092  3.58160414  1.21483096 11.44657219  9.26597142\n",
      "   4.10370268  4.18161798 14.15205666  2.07913113]\n",
      " [ 0.9143175   0.64478816  6.63477487  7.52739507  1.96629743  0.70986043\n",
      "  15.51887126  6.57975813  7.63913062  0.12958737]\n",
      " [14.36169595  8.51086264 13.08230922  3.56073338  5.90285668  7.66843812\n",
      "  17.43569283  2.12028403  3.62911512 13.19184398]\n",
      " [14.54713139  1.95977899  0.74333133 10.87761572  5.58552605  4.39352621\n",
      "   3.75662835 10.64759725  4.38286275 10.59080599]\n",
      " [ 8.93133026  5.51552187  1.63519872  6.06603912  8.57874172  6.99229651\n",
      "   3.30246759  8.46418042  8.88224559  5.09797049]\n",
      " [10.31880276  1.36013315  5.98582952  3.20046907  1.2761327   0.53036216\n",
      "  11.17109363  1.81264107  3.14840606  8.03104193]]\n"
     ]
    }
   ],
   "source": [
    "# based on distance function from previous question\n",
    "P0 = np.random.uniform(-10, 10, (10,2))\n",
    "P1 = np.random.uniform(-10,10,(10,2))\n",
    "p = np.random.uniform(-10, 10, (10,2))\n",
    "print(np.array([distance(P0,P1,p_i) for p_i in p]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 80. 给定任意一个数组，编写一个函数，接受数组和一个元素为参数，返回以元素为中心的子集（必要的时候可以进行填充）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:46.831657Z",
     "start_time": "2019-09-11T03:52:46.817848Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[7 9 1 5 1 6 6 3 7 6]\n",
      " [9 5 1 4 5 8 5 4 4 7]\n",
      " [3 8 4 7 5 1 5 6 0 9]\n",
      " [2 9 9 5 4 1 1 4 7 8]\n",
      " [4 2 8 8 1 4 0 4 5 3]\n",
      " [2 9 5 0 4 6 9 6 9 0]\n",
      " [2 0 0 3 1 1 4 5 9 2]\n",
      " [1 4 4 7 2 7 1 5 6 3]\n",
      " [3 3 4 6 6 1 9 8 4 1]\n",
      " [7 9 2 1 8 9 7 7 4 5]]\n",
      "[[0 0 0 0 0]\n",
      " [0 7 9 1 5]\n",
      " [0 9 5 1 4]\n",
      " [0 3 8 4 7]\n",
      " [0 2 9 9 5]]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/shensir/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:27: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "# Author: Nicolas Rougier\n",
    "\n",
    "Z = np.random.randint(0,10,(10,10))\n",
    "shape = (5,5)\n",
    "fill  = 0\n",
    "position = (1,1)\n",
    "\n",
    "R = np.ones(shape, dtype=Z.dtype)*fill\n",
    "P  = np.array(list(position)).astype(int)\n",
    "Rs = np.array(list(R.shape)).astype(int)\n",
    "Zs = np.array(list(Z.shape)).astype(int)\n",
    "\n",
    "R_start = np.zeros((len(shape),)).astype(int)\n",
    "R_stop  = np.array(list(shape)).astype(int)\n",
    "Z_start = (P-Rs//2)\n",
    "Z_stop  = (P+Rs//2)+Rs%2\n",
    "\n",
    "R_start = (R_start - np.minimum(Z_start,0)).tolist()\n",
    "Z_start = (np.maximum(Z_start,0)).tolist()\n",
    "R_stop = np.maximum(R_start, (R_stop - np.maximum(Z_stop-Zs,0))).tolist()\n",
    "Z_stop = (np.minimum(Z_stop,Zs)).tolist()\n",
    "\n",
    "r = [slice(start,stop) for start,stop in zip(R_start,R_stop)]\n",
    "z = [slice(start,stop) for start,stop in zip(Z_start,Z_stop)]\n",
    "R[r] = Z[z]\n",
    "print(Z)\n",
    "print(R)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PS: 感觉难度为三星的题目（64题及之后）很多出的不太好...考察的是更加灵活地运用Numpy，逻辑是没问题，但是缺乏具体的示例，没有依托实际的问题，就显得比较空洞Orz"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 81. 有数组Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]， 如何生成 = [[1,2,3,4], [2,3,4,5], [3,4,5,6], ..., [11,12,13,14]]？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:47.729156Z",
     "start_time": "2019-09-11T03:52:47.724062Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3  4]\n",
      " [ 2  3  4  5]\n",
      " [ 3  4  5  6]\n",
      " [ 4  5  6  7]\n",
      " [ 5  6  7  8]\n",
      " [ 6  7  8  9]\n",
      " [ 7  8  9 10]\n",
      " [ 8  9 10 11]\n",
      " [ 9 10 11 12]\n",
      " [10 11 12 13]\n",
      " [11 12 13 14]]\n"
     ]
    }
   ],
   "source": [
    "# 1， 答案的方法\n",
    "Z = np.arange(1,15,dtype=np.uint32)\n",
    "R = stride_tricks.as_strided(Z,(11,4),(4,4))\n",
    "print(R)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:47.915575Z",
     "start_time": "2019-09-11T03:52:47.910859Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3,  4],\n",
       "       [ 2,  3,  4,  5],\n",
       "       [ 3,  4,  5,  6],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 5,  6,  7,  8],\n",
       "       [ 6,  7,  8,  9],\n",
       "       [ 7,  8,  9, 10],\n",
       "       [ 8,  9, 10, 11],\n",
       "       [ 9, 10, 11, 12],\n",
       "       [10, 11, 12, 13],\n",
       "       [11, 12, 13, 14]])"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2， 76题的一个特殊形式\n",
    "z = np.arange(1, 15)\n",
    "rolling(z, 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 82. 计算矩阵的秩"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:50.079379Z",
     "start_time": "2019-09-11T03:52:49.796291Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n"
     ]
    }
   ],
   "source": [
    "# 1， 答案的方法\n",
    "Z = np.random.uniform(0,1,(10,10))\n",
    "U, S, V = np.linalg.svd(Z) # Singular Value Decomposition\n",
    "rank = np.sum(S > 1e-10)\n",
    "print(rank)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:50.086947Z",
     "start_time": "2019-09-11T03:52:50.082063Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 151,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2， 调用API\n",
    "np.linalg.matrix_rank(Z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 83. 找出数组中的众数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:50.448862Z",
     "start_time": "2019-09-11T03:52:50.440273Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 8, 0, 9, 3, 8, 0, 5, 5, 3, 8, 4, 2, 1, 6, 1, 7, 5, 2, 3, 3, 7,\n",
       "       0, 6, 0, 4, 2, 0, 9, 0, 1, 7, 5, 7, 9, 3, 7, 5, 0, 2, 9, 1, 7, 5,\n",
       "       0, 9, 2, 2, 2, 0])"
      ]
     },
     "execution_count": 152,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = np.random.randint(0,10,50)\n",
    "Z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:50.627034Z",
     "start_time": "2019-09-11T03:52:50.622786Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "print(np.bincount(Z).argmax())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果不限制在Numpy之内，我们可以直接调用Scipy提供的API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 154,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:52.311760Z",
     "start_time": "2019-09-11T03:52:50.974249Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ModeResult(mode=array([0]), count=array([9]))"
      ]
     },
     "execution_count": 154,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from scipy import stats\n",
    "stats.mode(Z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 84. 从10x10的矩阵中抽取出所有的3x3矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:52.333357Z",
     "start_time": "2019-09-11T03:52:52.318571Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[[1 0 3]\n",
      "   [4 4 1]\n",
      "   [4 1 4]]\n",
      "\n",
      "  [[0 3 1]\n",
      "   [4 1 1]\n",
      "   [1 4 0]]\n",
      "\n",
      "  [[3 1 3]\n",
      "   [1 1 2]\n",
      "   [4 0 4]]\n",
      "\n",
      "  [[1 3 3]\n",
      "   [1 2 2]\n",
      "   [0 4 2]]\n",
      "\n",
      "  [[3 3 2]\n",
      "   [2 2 1]\n",
      "   [4 2 1]]\n",
      "\n",
      "  [[3 2 0]\n",
      "   [2 1 1]\n",
      "   [2 1 0]]\n",
      "\n",
      "  [[2 0 1]\n",
      "   [1 1 1]\n",
      "   [1 0 1]]\n",
      "\n",
      "  [[0 1 2]\n",
      "   [1 1 1]\n",
      "   [0 1 4]]]\n",
      "\n",
      "\n",
      " [[[4 4 1]\n",
      "   [4 1 4]\n",
      "   [1 1 1]]\n",
      "\n",
      "  [[4 1 1]\n",
      "   [1 4 0]\n",
      "   [1 1 1]]\n",
      "\n",
      "  [[1 1 2]\n",
      "   [4 0 4]\n",
      "   [1 1 1]]\n",
      "\n",
      "  [[1 2 2]\n",
      "   [0 4 2]\n",
      "   [1 1 4]]\n",
      "\n",
      "  [[2 2 1]\n",
      "   [4 2 1]\n",
      "   [1 4 4]]\n",
      "\n",
      "  [[2 1 1]\n",
      "   [2 1 0]\n",
      "   [4 4 0]]\n",
      "\n",
      "  [[1 1 1]\n",
      "   [1 0 1]\n",
      "   [4 0 1]]\n",
      "\n",
      "  [[1 1 1]\n",
      "   [0 1 4]\n",
      "   [0 1 4]]]\n",
      "\n",
      "\n",
      " [[[4 1 4]\n",
      "   [1 1 1]\n",
      "   [4 4 3]]\n",
      "\n",
      "  [[1 4 0]\n",
      "   [1 1 1]\n",
      "   [4 3 3]]\n",
      "\n",
      "  [[4 0 4]\n",
      "   [1 1 1]\n",
      "   [3 3 1]]\n",
      "\n",
      "  [[0 4 2]\n",
      "   [1 1 4]\n",
      "   [3 1 4]]\n",
      "\n",
      "  [[4 2 1]\n",
      "   [1 4 4]\n",
      "   [1 4 4]]\n",
      "\n",
      "  [[2 1 0]\n",
      "   [4 4 0]\n",
      "   [4 4 0]]\n",
      "\n",
      "  [[1 0 1]\n",
      "   [4 0 1]\n",
      "   [4 0 1]]\n",
      "\n",
      "  [[0 1 4]\n",
      "   [0 1 4]\n",
      "   [0 1 0]]]\n",
      "\n",
      "\n",
      " [[[1 1 1]\n",
      "   [4 4 3]\n",
      "   [2 3 3]]\n",
      "\n",
      "  [[1 1 1]\n",
      "   [4 3 3]\n",
      "   [3 3 1]]\n",
      "\n",
      "  [[1 1 1]\n",
      "   [3 3 1]\n",
      "   [3 1 0]]\n",
      "\n",
      "  [[1 1 4]\n",
      "   [3 1 4]\n",
      "   [1 0 0]]\n",
      "\n",
      "  [[1 4 4]\n",
      "   [1 4 4]\n",
      "   [0 0 2]]\n",
      "\n",
      "  [[4 4 0]\n",
      "   [4 4 0]\n",
      "   [0 2 3]]\n",
      "\n",
      "  [[4 0 1]\n",
      "   [4 0 1]\n",
      "   [2 3 0]]\n",
      "\n",
      "  [[0 1 4]\n",
      "   [0 1 0]\n",
      "   [3 0 3]]]\n",
      "\n",
      "\n",
      " [[[4 4 3]\n",
      "   [2 3 3]\n",
      "   [4 0 0]]\n",
      "\n",
      "  [[4 3 3]\n",
      "   [3 3 1]\n",
      "   [0 0 2]]\n",
      "\n",
      "  [[3 3 1]\n",
      "   [3 1 0]\n",
      "   [0 2 1]]\n",
      "\n",
      "  [[3 1 4]\n",
      "   [1 0 0]\n",
      "   [2 1 4]]\n",
      "\n",
      "  [[1 4 4]\n",
      "   [0 0 2]\n",
      "   [1 4 1]]\n",
      "\n",
      "  [[4 4 0]\n",
      "   [0 2 3]\n",
      "   [4 1 4]]\n",
      "\n",
      "  [[4 0 1]\n",
      "   [2 3 0]\n",
      "   [1 4 1]]\n",
      "\n",
      "  [[0 1 0]\n",
      "   [3 0 3]\n",
      "   [4 1 0]]]\n",
      "\n",
      "\n",
      " [[[2 3 3]\n",
      "   [4 0 0]\n",
      "   [4 0 2]]\n",
      "\n",
      "  [[3 3 1]\n",
      "   [0 0 2]\n",
      "   [0 2 2]]\n",
      "\n",
      "  [[3 1 0]\n",
      "   [0 2 1]\n",
      "   [2 2 2]]\n",
      "\n",
      "  [[1 0 0]\n",
      "   [2 1 4]\n",
      "   [2 2 4]]\n",
      "\n",
      "  [[0 0 2]\n",
      "   [1 4 1]\n",
      "   [2 4 4]]\n",
      "\n",
      "  [[0 2 3]\n",
      "   [4 1 4]\n",
      "   [4 4 1]]\n",
      "\n",
      "  [[2 3 0]\n",
      "   [1 4 1]\n",
      "   [4 1 0]]\n",
      "\n",
      "  [[3 0 3]\n",
      "   [4 1 0]\n",
      "   [1 0 3]]]\n",
      "\n",
      "\n",
      " [[[4 0 0]\n",
      "   [4 0 2]\n",
      "   [1 4 0]]\n",
      "\n",
      "  [[0 0 2]\n",
      "   [0 2 2]\n",
      "   [4 0 3]]\n",
      "\n",
      "  [[0 2 1]\n",
      "   [2 2 2]\n",
      "   [0 3 3]]\n",
      "\n",
      "  [[2 1 4]\n",
      "   [2 2 4]\n",
      "   [3 3 4]]\n",
      "\n",
      "  [[1 4 1]\n",
      "   [2 4 4]\n",
      "   [3 4 1]]\n",
      "\n",
      "  [[4 1 4]\n",
      "   [4 4 1]\n",
      "   [4 1 2]]\n",
      "\n",
      "  [[1 4 1]\n",
      "   [4 1 0]\n",
      "   [1 2 2]]\n",
      "\n",
      "  [[4 1 0]\n",
      "   [1 0 3]\n",
      "   [2 2 0]]]\n",
      "\n",
      "\n",
      " [[[4 0 2]\n",
      "   [1 4 0]\n",
      "   [2 1 4]]\n",
      "\n",
      "  [[0 2 2]\n",
      "   [4 0 3]\n",
      "   [1 4 3]]\n",
      "\n",
      "  [[2 2 2]\n",
      "   [0 3 3]\n",
      "   [4 3 4]]\n",
      "\n",
      "  [[2 2 4]\n",
      "   [3 3 4]\n",
      "   [3 4 0]]\n",
      "\n",
      "  [[2 4 4]\n",
      "   [3 4 1]\n",
      "   [4 0 2]]\n",
      "\n",
      "  [[4 4 1]\n",
      "   [4 1 2]\n",
      "   [0 2 3]]\n",
      "\n",
      "  [[4 1 0]\n",
      "   [1 2 2]\n",
      "   [2 3 2]]\n",
      "\n",
      "  [[1 0 3]\n",
      "   [2 2 0]\n",
      "   [3 2 4]]]]\n"
     ]
    }
   ],
   "source": [
    "Z = np.random.randint(0,5,(10,10))\n",
    "n = 3\n",
    "i = 1 + (Z.shape[0]-3)\n",
    "j = 1 + (Z.shape[1]-3)\n",
    "C = stride_tricks.as_strided(Z, shape=(i, j, n, n), strides=Z.strides + Z.strides)\n",
    "print(C)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 85. 构造二维数组的子类，使得Z[i, j] = Z[j, i]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:52.461549Z",
     "start_time": "2019-09-11T03:52:52.338431Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 8 18 10 16 17]\n",
      " [18  7  5 14  8]\n",
      " [10  5  2 42  4]\n",
      " [16 14 42  6 13]\n",
      " [17  8  4 13  0]]\n"
     ]
    }
   ],
   "source": [
    "# Author: Eric O. Lebigot\n",
    "# Note: only works for 2d array and value setting using indices\n",
    "\n",
    "class Symetric(np.ndarray):\n",
    "    def __setitem__(self, index, value):\n",
    "        i,j = index\n",
    "        super(Symetric, self).__setitem__((i,j), value)\n",
    "        super(Symetric, self).__setitem__((j,i), value)\n",
    "\n",
    "def symetric(Z):\n",
    "    return np.asarray(Z + Z.T - np.diag(Z.diagonal())).view(Symetric)\n",
    "\n",
    "S = symetric(np.random.randint(0,10,(5,5)))\n",
    "S[2,3] = 42\n",
    "print(S)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 86. 给定p个(n, n)矩阵和p个(n, 1)向量， 计算张量乘法(tensor product)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:52.560636Z",
     "start_time": "2019-09-11T03:52:52.464402Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]\n",
      " [200.]]\n"
     ]
    }
   ],
   "source": [
    "p, n = 10, 20\n",
    "M = np.ones((p,n,n))\n",
    "V = np.ones((p,n,1))\n",
    "S = np.tensordot(M, V, axes=[[0, 2], [0, 1]])\n",
    "print(S)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 87. 给定16x16的数组，将其分成4x4的小块，求每块的和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:52.660295Z",
     "start_time": "2019-09-11T03:52:52.563353Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[16. 16. 16. 16.]\n",
      " [16. 16. 16. 16.]\n",
      " [16. 16. 16. 16.]\n",
      " [16. 16. 16. 16.]]\n"
     ]
    }
   ],
   "source": [
    "Z = np.ones((16,16))\n",
    "k = 4\n",
    "S = np.add.reduceat(np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),\n",
    "                                       np.arange(0, Z.shape[1], k), axis=1)\n",
    "print(S)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 88. 用数组实现生存游戏"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:53.018120Z",
     "start_time": "2019-09-11T03:52:52.989758Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 0 0 ... 0 0 0]\n",
      " [0 0 0 ... 0 0 0]\n",
      " [0 0 0 ... 0 0 0]\n",
      " ...\n",
      " [0 0 0 ... 0 0 0]\n",
      " [0 0 0 ... 0 0 0]\n",
      " [0 0 0 ... 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "def iterate(Z):\n",
    "    # Count neighbours\n",
    "    N = (Z[0:-2,0:-2] + Z[0:-2,1:-1] + Z[0:-2,2:] +\n",
    "         Z[1:-1,0:-2]                + Z[1:-1,2:] +\n",
    "         Z[2:  ,0:-2] + Z[2:  ,1:-1] + Z[2:  ,2:])\n",
    "\n",
    "    # Apply rules\n",
    "    birth = (N==3) & (Z[1:-1,1:-1]==0)\n",
    "    survive = ((N==2) | (N==3)) & (Z[1:-1,1:-1]==1)\n",
    "    Z[...] = 0\n",
    "    Z[1:-1,1:-1][birth | survive] = 1\n",
    "    return Z\n",
    "\n",
    "Z = np.random.randint(0,2,(50,50))\n",
    "for i in range(100): Z = iterate(Z)\n",
    "print(Z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 89. 获取数组最大的n个值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:53.380110Z",
     "start_time": "2019-09-11T03:52:53.352993Z"
    }
   },
   "outputs": [],
   "source": [
    "Z = np.arange(10000)\n",
    "np.random.shuffle(Z)\n",
    "n = 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:53.549524Z",
     "start_time": "2019-09-11T03:52:53.543952Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[9995 9996 9997 9998 9999]\n"
     ]
    }
   ],
   "source": [
    "# 较慢\n",
    "print (Z[np.argsort(Z)[-n:]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:53.965524Z",
     "start_time": "2019-09-11T03:52:53.960038Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[9999 9997 9998 9996 9995]\n"
     ]
    }
   ],
   "source": [
    "# 较快\n",
    "print (Z[np.argpartition(-Z,n)[:n]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 90. 给定任意大小的数组，计算其笛卡尔积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:54.329733Z",
     "start_time": "2019-09-11T03:52:54.322385Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 4 6]\n",
      " [1 4 7]\n",
      " [1 5 6]\n",
      " [1 5 7]\n",
      " [2 4 6]\n",
      " [2 4 7]\n",
      " [2 5 6]\n",
      " [2 5 7]\n",
      " [3 4 6]\n",
      " [3 4 7]\n",
      " [3 5 6]\n",
      " [3 5 7]]\n"
     ]
    }
   ],
   "source": [
    "def cartesian(arrays):\n",
    "    arrays = [np.asarray(a) for a in arrays]\n",
    "    shape = (len(x) for x in arrays)\n",
    "\n",
    "    ix = np.indices(shape, dtype=int)\n",
    "    ix = ix.reshape(len(arrays), -1).T\n",
    "\n",
    "    for n, arr in enumerate(arrays):\n",
    "        ix[:, n] = arrays[n][ix[:, n]]\n",
    "\n",
    "    return ix\n",
    "\n",
    "print (cartesian(([1, 2, 3], [4, 5], [6, 7])))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 91. 将一般的数组转化为结构化数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:54.976811Z",
     "start_time": "2019-09-11T03:52:54.972026Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([['Hello', '2.5', '3'],\n",
       "       ['World', '3.6', '2']], dtype='<U5')"
      ]
     },
     "execution_count": 164,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = np.array([(\"Hello\", 2.5, 3),\n",
    "              (\"World\", 3.6, 2)])\n",
    "Z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:55.165457Z",
     "start_time": "2019-09-11T03:52:55.159322Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "rec.array([(b'Hello', 2.5, 3), (b'World', 3.6, 2)],\n",
       "          dtype=[('col1', 'S8'), ('col2', '<f8'), ('col3', '<i8')])"
      ]
     },
     "execution_count": 165,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "R = np.core.records.fromarrays(Z.T, \n",
    "                               names='col1, col2, col3',\n",
    "                               formats = 'S8, f8, i8')\n",
    "R"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 92. 用三种方法计算大向量的三次方"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:52:56.345253Z",
     "start_time": "2019-09-11T03:52:55.506009Z"
    }
   },
   "outputs": [],
   "source": [
    "x = np.random.rand(int(5e7))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:28.997283Z",
     "start_time": "2019-09-11T03:52:56.348050Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.07 s ± 79.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit np.power(x,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:31.057562Z",
     "start_time": "2019-09-11T03:53:28.999904Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "230 ms ± 3.23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit x*x*x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:33.596714Z",
     "start_time": "2019-09-11T03:53:31.060209Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "316 ms ± 16.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "%timeit np.einsum('i,i,i->i',x,x,x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 93. 考虑形状（8,3）和（2,2）的两个数组A和B. 如何查找包含B的每一行元素的A行，不考虑B中元素的顺序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:33.606696Z",
     "start_time": "2019-09-11T03:53:33.599354Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2 3 4 5 6]\n"
     ]
    }
   ],
   "source": [
    "A = np.random.randint(0,5,(8,3))\n",
    "B = np.random.randint(0,5,(2,2))\n",
    "\n",
    "C = (A[..., np.newaxis, np.newaxis] == B)\n",
    "rows = np.where(C.any((3,1)).all(1))[0]\n",
    "print(rows)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 94. 给定（10， 3）的矩阵， 找出包含不同元素的行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:33.704025Z",
     "start_time": "2019-09-11T03:53:33.609205Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3, 4],\n",
       "       [0, 2, 2],\n",
       "       [0, 1, 1],\n",
       "       [2, 2, 3],\n",
       "       [0, 3, 0],\n",
       "       [4, 2, 2],\n",
       "       [0, 2, 4],\n",
       "       [4, 2, 1],\n",
       "       [1, 0, 3],\n",
       "       [0, 0, 0]])"
      ]
     },
     "execution_count": 171,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = np.random.randint(0,5,(10,3))\n",
    "Z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:33.804894Z",
     "start_time": "2019-09-11T03:53:33.706491Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3, 4],\n",
       "       [0, 2, 2],\n",
       "       [0, 1, 1],\n",
       "       [2, 2, 3],\n",
       "       [0, 3, 0],\n",
       "       [4, 2, 2],\n",
       "       [0, 2, 4],\n",
       "       [4, 2, 1],\n",
       "       [1, 0, 3]])"
      ]
     },
     "execution_count": 172,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 适用于任意数据类型\n",
    "E = np.all(Z[:,1:] == Z[:,:-1], axis=1)\n",
    "U = Z[~E]\n",
    "U"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 173,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:33.902959Z",
     "start_time": "2019-09-11T03:53:33.811297Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3, 4],\n",
       "       [0, 2, 2],\n",
       "       [0, 1, 1],\n",
       "       [2, 2, 3],\n",
       "       [0, 3, 0],\n",
       "       [4, 2, 2],\n",
       "       [0, 2, 4],\n",
       "       [4, 2, 1],\n",
       "       [1, 0, 3]])"
      ]
     },
     "execution_count": 173,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 仅适用于数值类型\n",
    "U = Z[Z.max(axis=1) != Z.min(axis=1),:]\n",
    "U"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 95. 将给定的整数向量转化为二进制矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:34.001270Z",
     "start_time": "2019-09-11T03:53:33.905784Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 0 0 1]\n",
      " [0 0 0 0 0 0 1 0]\n",
      " [0 0 0 0 0 0 1 1]\n",
      " [0 0 0 0 1 1 1 1]\n",
      " [0 0 0 1 0 0 0 0]\n",
      " [0 0 1 0 0 0 0 0]\n",
      " [0 1 0 0 0 0 0 0]\n",
      " [1 0 0 0 0 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "I = np.array([0, 1, 2, 3, 15, 16, 32, 64, 128], dtype=np.uint8)\n",
    "print(np.unpackbits(I[:, np.newaxis], axis=1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 96. 给定二维数组，抽取所有不同的行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:34.132630Z",
     "start_time": "2019-09-11T03:53:34.004373Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0],\n",
       "       [0, 1, 1],\n",
       "       [0, 0, 0],\n",
       "       [1, 1, 1],\n",
       "       [0, 1, 0],\n",
       "       [0, 0, 0]])"
      ]
     },
     "execution_count": 175,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = np.random.randint(0,2,(6,3))\n",
    "Z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 176,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:34.279301Z",
     "start_time": "2019-09-11T03:53:34.135614Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0],\n",
       "       [0, 1, 0],\n",
       "       [0, 1, 1],\n",
       "       [1, 1, 1]])"
      ]
     },
     "execution_count": 176,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "uZ = np.unique(Z, axis=0)\n",
    "uZ"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 97. 考虑两个数组A，B， 使用np.einsum写出矩阵间的outer, inner, sum, mul函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 177,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:34.377630Z",
     "start_time": "2019-09-11T03:53:34.281669Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.05623017, 0.0435339 , 0.06410929, 0.00515166, 0.04477097,\n",
       "        0.00687832, 0.01534161, 0.03621964, 0.02564694, 0.01010714],\n",
       "       [0.25008018, 0.19361432, 0.28512209, 0.02291169, 0.19911611,\n",
       "        0.03059089, 0.06823086, 0.16108458, 0.11406317, 0.04495087],\n",
       "       [0.37356092, 0.28921422, 0.42590529, 0.03422467, 0.29743259,\n",
       "        0.04569558, 0.10192084, 0.24062245, 0.17038353, 0.06714602],\n",
       "       [0.20315391, 0.15728358, 0.23162038, 0.01861243, 0.16175298,\n",
       "        0.02485066, 0.05542769, 0.13085788, 0.0926598 , 0.03651607],\n",
       "       [0.32736782, 0.25345111, 0.37323949, 0.02999258, 0.26065323,\n",
       "        0.04004504, 0.08931771, 0.21086801, 0.14931456, 0.05884301],\n",
       "       [0.45291908, 0.35065402, 0.51638333, 0.04149526, 0.36061828,\n",
       "        0.05540302, 0.1235726 , 0.29173956, 0.20657929, 0.08141032],\n",
       "       [0.1605851 , 0.12432643, 0.18308672, 0.01471239, 0.12785931,\n",
       "        0.01964346, 0.04381338, 0.10343796, 0.07324389, 0.0288645 ],\n",
       "       [0.39477812, 0.30564078, 0.45009551, 0.03616854, 0.31432592,\n",
       "        0.04829096, 0.10770966, 0.25428912, 0.18006083, 0.07095973],\n",
       "       [0.54263895, 0.42011596, 0.61867499, 0.04971516, 0.43205405,\n",
       "        0.06637794, 0.1480514 , 0.34953097, 0.2475011 , 0.0975371 ],\n",
       "       [0.38241351, 0.29606798, 0.43599833, 0.03503572, 0.3044811 ,\n",
       "        0.04677847, 0.10433615, 0.24632468, 0.17442125, 0.06873724]])"
      ]
     },
     "execution_count": 177,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.random.uniform(0,1,10)\n",
    "B = np.random.uniform(0,1,10)\n",
    "\n",
    "np.einsum('i->', A)       # np.sum(A)\n",
    "np.einsum('i,i->i', A, B) # A * B\n",
    "np.einsum('i,i', A, B)    # np.inner(A, B)\n",
    "np.einsum('i,j->ij', A, B)    # np.outer(A, B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 98. 用两个向量(X, Y)描述一条轨道，如何对其进行等距抽样"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 178,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:34.510627Z",
     "start_time": "2019-09-11T03:53:34.380481Z"
    }
   },
   "outputs": [],
   "source": [
    "phi = np.arange(0, 10*np.pi, 0.1)\n",
    "a = 1\n",
    "x = a*phi*np.cos(phi)\n",
    "y = a*phi*np.sin(phi)\n",
    "\n",
    "dr = (np.diff(x)**2 + np.diff(y)**2)**.5 # segment lengths\n",
    "r = np.zeros_like(x)\n",
    "r[1:] = np.cumsum(dr)                # integrate path\n",
    "r_int = np.linspace(0, r.max(), 200) # regular spaced path\n",
    "x_int = np.interp(r_int, r, x)       # integrate path\n",
    "y_int = np.interp(r_int, r, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 99. 给定一个二维数组和一个整数n，提取所有仅包含整数，且元素和为n的行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 179,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:53:34.612858Z",
     "start_time": "2019-09-11T03:53:34.512533Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2. 0. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "X = np.asarray([[1.0, 0.0, 3.0, 8.0],\n",
    "                [2.0, 0.0, 1.0, 1.0],\n",
    "                [1.5, 2.5, 1.0, 0.0]])\n",
    "n = 4\n",
    "M = np.logical_and.reduce(np.mod(X, 1) == 0, axis=-1)\n",
    "M &= (X.sum(axis=-1) == n)\n",
    "print(X[M])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 100. 给定一个向量，计算其均值的95%的置信区间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 180,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-09-11T03:54:49.491615Z",
     "start_time": "2019-09-11T03:54:49.479049Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-0.29266392  0.11041998]\n"
     ]
    }
   ],
   "source": [
    "X = np.random.randn(100) \n",
    "N = 1000  # 再抽样次数\n",
    "idx = np.random.randint(0, X.size, (N, X.size))\n",
    "means = X[idx].mean(axis=1)\n",
    "confint = np.percentile(means, [2.5, 97.5])\n",
    "print(confint)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "275.2px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
